using BPA.Message;
using BPA.Message.Enum;
using BPA.Message.IOT;
using BPASmartClient.Device;
using BPASmartClient.DRCoffee;
using BPASmartClient.EventBus;
using BPASmartClient.GSIceCream;
using BPASmartClient.Helper;
using BPASmartClient.Lebai;
using BPASmartClient.Message;
using BPASmartClient.Model;
using BPASmartClient.Model.冰淇淋.Enum;
using BPASmartClient.Model.单片机;
using BPASmartClient.Model.单片机.Enum;
using BPASmartClient.Model.咖啡机.Enum;
using BPASmartClient.SCChip;
using Robotc;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using static BPASmartClient.EventBus.EventBus;

namespace BPASmartClient.MORKIC
{
    /*
     * 冰淇淋咖啡机组合套装
     * 物料位置：
     * 1：冰淇料
     * 2：冰淇淋杯
     * 5：咖啡
     * 6：咖啡杯
     */
    public class Control_MORKIC : BaseDevice
    {

        //咖啡机主控程序
        private CoffeeMachine coffeeMachine;
        //单片机主控程序
        private ICChipMachine icchipMachine;
        //广绅单口冰淇淋机
        private IceCreamMachine iceCreamMachine;
        //物料存放位置
        private Dictionary<string, PolymerBatching> batchings = new Dictionary<string, PolymerBatching>();
        /// <summary>
        /// 获取乐百机器人的数据
        /// </summary>
        SignalResult lebai = new SignalResult();
        /// <summary>
        /// 咖啡位置是否有东西
        /// </summary>
        private bool IsCoffeeMake = false;

        private bool enableFunny = false;
        private DateTime lastRecvdOrder = DateTime.Now;
        private bool working = false;
        private bool IceIsOK = true;

        public void ConnectOk()
        {

        }
        /// <summary>
        /// 当前正在制作咖啡
        /// </summary>
        SimOrderData MakeCoffeeOrder = new SimOrderData();
        /// <summary>
        /// 咖啡订单队列
        /// </summary>
        ConcurrentQueue<SimOrderData> morkOrderPushesCoffee = new ConcurrentQueue<SimOrderData>();
        /// <summary>
        /// 冰淇淋订单队列
        /// </summary>
        ConcurrentQueue<SimOrderData> morkOrderPushesIceCream = new ConcurrentQueue<SimOrderData>();
        /// <summary>
        /// 等待取餐的订单，只有一个
        /// </summary>
        ConcurrentQueue<SimOrderData> WaitTakeMealOrder = new ConcurrentQueue<SimOrderData>();

        public void Init()
        {

            ActionManage.GetInstance.Register(new Action<object>((s) =>
            {
                if (s is DrCoffeeDrinksCode cf)
                {
                    DoCoffee(new SimOrderData { Loc = ((int)cf).ToString() });
                }
                else if (s is Dictionary<string, string> ms)
                {
                    if (ms.ContainsKey("Button"))
                    {
                        switch (ms["Button"])
                        {
                            case "启动示教":
                                LebaiRobot.GetInstance.StartTeachMode();
                                break;
                            case "停止示教":
                                LebaiRobot.GetInstance.EndtTeachMode();
                                break;
                            case "启动机器人":
                                LebaiRobot.GetInstance.StartRobot();
                                break;
                            case "急停":
                                LebaiRobot.GetInstance.EStopRobot();
                                break;
                            default:
                                break;
                        }
                    }
                }
            }), "SimCoffee");

            //构建所有商品物料信息
            batchings = PolymerBatching.BuildAll();

            EventBus.EventBus.GetInstance().Subscribe<DRCoffee_CoffeEndCookEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
            {
                if (MakeCoffeeOrder != null)
                    MakeCoffeeOrder.OrderStatus = 1;
            });

            System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None);
            //一系列外围基础配置
            var com_Coffee = config.AppSettings.Settings["COM_Coffee"].Value;
            var baud_Coffee = config.AppSettings.Settings["BAUD_Coffee"].Value;
            var com_IceCream = config.AppSettings.Settings["COM_IceCream"].Value;
            var baud_IceCream = config.AppSettings.Settings["BAUD_IceCream"].Value;
            var iceCreamCXBThreshold = int.Parse(config.AppSettings.Settings["IceCream_CXB_Threshold"].Value);

            var com_ICChip = config.AppSettings.Settings["COM_ICChip"].Value;
            var baud_ICChip = config.AppSettings.Settings["BAUD_IChip"].Value;


            if (iceCreamCXBThreshold > 0)
            {
                //设置冰淇淋成型比
                MorkIStatus.GetInstance().CXB_Threshold = (byte)iceCreamCXBThreshold;
            }
            //咖啡机创建
            coffeeMachine = new CoffeeMachine();
            //单片机机创建
            icchipMachine = new ICChipMachine();
            //冰淇淋机创建
            iceCreamMachine = new IceCreamMachine();

            Main();
            ReadRobotData();
            OrderMake();
        }

        private int NoOrderTime = 0;

        public override DeviceClientType DeviceType => DeviceClientType.MORKT;

        //订单制作
        public void OrderMake()
        {
            ThreadManage.GetInstance().StartLong(new Action(() =>
            {
                while (IsHealth && (morkOrderPushesCoffee.Count > 0 || morkOrderPushesIceCream.Count > 0 || IsCoffeeMake))
                {
                    working = true; NoOrderTime = 0;
                    //1.有咖啡订单 取杯去制作
                    if (!IsCoffeeMake)//位置无杯子
                    {
                        if (morkOrderPushesCoffee.Count > 0 && morkOrderPushesCoffee.TryDequeue(out SimOrderData simOrder))
                        {
                            IsCoffeeMake = true; MakeCoffeeOrder = simOrder;
                            MessageLog.GetInstance.Show($"开始制作 [咖啡] 订单[{simOrder.morkOrder.SortNum}]");
                            DoCoffee(simOrder);
                        }
                    }

                    if (!LebaiRobot.GetInstance.GetInput())//取餐口是否有餐饮
                    {
                        //取餐位的订单完成
                        if (WaitTakeMealOrder.TryDequeue(out SimOrderData waitOrder)) OrderChange(waitOrder.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COMPLETED_TAKE);


                        //1.制作冰淇淋
                        if (morkOrderPushesIceCream.Count > 0 && MorkIStatus.GetInstance().CurrentMode != MORKI_MODE.制冷模式) new GSIceCream_ModeSetEvent() { Mode = MORKI_MODE.制冷模式 }.Publish();

                        if (MorkIStatus.GetInstance().CXB >= 86 && morkOrderPushesIceCream.Count > 0)//成型比大于80 我才会制作
                        {
                            if (LebaiRobot.GetInstance.GetInput(3))
                            {
                                if (IceIsOK) MessageLog.GetInstance.Show("请擦拭冰淇淋机出口");
                                IceIsOK = false;

                            }
                            else if (morkOrderPushesIceCream.TryDequeue(out SimOrderData order))
                            {
                                IceIsOK = true;
                                MessageLog.GetInstance.Show($"开始制作 [冰淇淋] 订单[{order.morkOrder.SortNum}]");
                                DoIceCream(order);
                            }
                        }

                        //2.取咖啡到取餐口
                        if (IsCoffeeMake)
                        {
                            if (MakeCoffeeOrder != null && MakeCoffeeOrder.OrderStatus == 1)
                            {
                                MessageLog.GetInstance.Show($"将咖啡移动到取餐位 [咖啡] 订单[{MakeCoffeeOrder.morkOrder.SortNum}]");
                                DoCoffeeQC(MakeCoffeeOrder);
                                MakeCoffeeOrder = null;
                                IsCoffeeMake = false;
                            }
                        }
                    }
                    working = false;
                    lastRecvdOrder = DateTime.Now;
                }

                if (IsHealth == false && (morkOrderPushesCoffee.Count > 0 || morkOrderPushesIceCream.Count > 0 || IsCoffeeMake))
                {
                    MessageLog.GetInstance.Show($"机器连接问题 订单,不允许制作,请检查设备连接后尝试," +
                        $"乐白：{LebaiRobot.GetInstance.IsConnected}咖啡机：{MorkIStatus.GetInstance().CanDo}单片机：{ChipStatus.GetInstance().CanDo}");

                    if (LebaiRobot.GetInstance.IsConnected && IsCoffeeMake && !LebaiRobot.GetInstance.GetInput())//乐白有订单
                    {
                        MessageLog.GetInstance.Show($"将咖啡移动到取餐位 [咖啡] 订单[{MakeCoffeeOrder.morkOrder.SortNum}]");
                        DoCoffeeQC(MakeCoffeeOrder);
                        MakeCoffeeOrder = null;
                        IsCoffeeMake = false;
                    }
                }

                if (!LebaiRobot.GetInstance.GetInput())
                {
                    if (WaitTakeMealOrder.TryDequeue(out SimOrderData waitOrder)) OrderChange(waitOrder.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COMPLETED_TAKE);
                }


                Thread.Sleep(1000);
            }), "订单制作");
        }

        private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS)
        {
            EventBus.EventBus.GetInstance().Publish(new OrderStatusChangedEvent() { Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType });
        }

        public void Main()
        {
            //咖啡机开启主线程
            coffeeMachine.Start();
            //单片机开启主线程
            icchipMachine.Start();
            //冰淇淋机开启主线程
            iceCreamMachine.Start();
            new GSIceCream_ModeSetEvent() { Mode = MORKI_MODE.制冷模式 }.Publish();
            //开始心跳刷新，根据咖啡机及冰淇淋机来判断
            //ThreadManage.GetInstance().StartLong(new Action(() =>
            //{
            //    GeneralConfig.Healthy =
            //             LebaiRobot.GetInstance.IsConnected &&
            //             MorkCStatus.GetInstance().CanDo &&
            //             ChipStatus.GetInstance().CanDo;
            //    //GeneralConfig.Healthy = true;
            //    Thread.Sleep(100);
            //}), "MORK-IC心跳刷新");
            ThreadManage.GetInstance().Start(new Action(() =>
            {
                while (!LebaiRobot.GetInstance.IsConnected)
                {
                    Thread.Sleep(10);
                }
                //LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_欢迎);
            }), "MORK-IC欢迎");

        }

        public void DataParse<T>(T order)
        {
            if (order is MorkOrderPush morkOrderPush)
            {
                //商品类型
                GOODS_TYPE currentGoodsType = GOODS_TYPE.NEITHER;
                string loc_coffe = string.Empty;
                string loc_cup = string.Empty;
                #region 订单分类
                //遍历物料
                foreach (var item in morkOrderPush.GoodBatchings)
                {
                    var res = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingId == item.BatchingId);
                    if (res != null)
                    {
                        //验证商品是咖啡还是冰淇淋
                        if (ValidateGoodsByBatching(res.BatchingLoc) != GOODS_TYPE.NEITHER)
                        {
                            //获取当前物料所属商品类型
                            currentGoodsType = ValidateGoodsByBatching(res.BatchingLoc);
                        }
                        //获取主料和容器位置
                        switch (batchings[res.BatchingLoc].BatchingClass)
                        {
                            case BATCHING_CLASS.HOLDER:
                                loc_cup = res.BatchingLoc;
                                break;
                            case BATCHING_CLASS.MAIN_MATERIAL:
                                loc_coffe = res.BatchingLoc;
                                break;
                        }
                    }
                }
                //根据商品类型执行具体制作流程
                switch (currentGoodsType)
                {
                    case GOODS_TYPE.COFFEE:
                        morkOrderPushesCoffee.Enqueue(new SimOrderData { Loc = loc_coffe, morkOrder = morkOrderPush });
                        break;
                    case GOODS_TYPE.ICECREAM:
                        morkOrderPushesIceCream.Enqueue(new SimOrderData { Loc = loc_coffe, morkOrder = morkOrderPush });
                        break;
                    case GOODS_TYPE.NEITHER:
                        MessageLog.GetInstance.Show("未知的商品类型");
                        break;
                }
                #endregion


            }
        }

        /// <summary>
        /// 验证当前是做咖啡还是做冰淇淋
        /// </summary>
        /// <param name="batchingLoc">物料位置</param>
        private GOODS_TYPE ValidateGoodsByBatching(string batchingLoc)
        {
            if (batchings.ContainsKey(batchingLoc))
                return batchings[batchingLoc].GoodsType;
            return GOODS_TYPE.NEITHER;
        }

        private void Wait(int value = 101)
        {
            while (!(lebai.Ok && lebai.Value == value))
            {
                Thread.Sleep(5);
            }
        }

        /// <summary>
        /// 做咖啡-接杯子 并且 回到 安全位置
        /// </summary>
        private void DoCoffee(SimOrderData order)
        {
            #region 且时且多入场设备程序
            int checkeNum = 0;
            // are.Reset();
            LebaiRobot.GetInstance.SetValue(0);
            OrderChange(order.morkOrder.SuborderId, ORDER_STATUS.COOKING);
            //SimpleFactory.GetInstance.OrderChanged(order.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COOKING);
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_取咖啡杯);
            Wait();
            new SCChip_TakeCupEvent() { Cup = IC_CUP.CUP_COFFEE }.Publish();//落碗控制
            Thread.Sleep(500);
            MessageLog.GetInstance.Show("尝试取咖啡杯!");
            LebaiRobot.GetInstance.SetValue(1);

            int count = 2;
        p:
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_咖啡杯检测);
            Wait();
            LebaiRobot.GetInstance.SetValue(1);

            if (!LebaiRobot.GetInstance.GetInput())
            {
                if (count >= 3)
                {
                    //退出循环回到初始位置
                    DeviceProcessLogShow($"执行{count}次取咖啡杯,仍为成功,订单默认废弃,机器人回到初始位置!");
                    LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_咖啡杯回原点);
                    Wait();
                    LebaiRobot.GetInstance.SetValue(1);
                    return;
                }
                DeviceProcessLogShow("执行二次取咖啡杯");
                LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_二次取咖啡杯);
                Wait();
                new SCChip_TakeCupEvent() { Cup = IC_CUP.CUP_COFFEE }.Publish();//落碗控制
                LebaiRobot.GetInstance.SetValue(1);
                count++;
                goto p;
            }

            DeviceProcessLogShow("咖啡杯取杯完成");
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_接咖啡后回原点);
            Wait();
            LebaiRobot.GetInstance.SetValue(1);
            //加场景 回初始位置
            new DRCoffee_MakeCoffeeEvent() { DrinkCode = (Model.咖啡机.Enum.DrCoffeeDrinksCode)int.Parse(order.Loc) }.Publish();  //接咖啡控制
            DeviceProcessLogShow($"发送咖啡机制作{order.Loc}!");
            #endregion

        }

        /// <summary>
        /// 将咖啡杯子 取走到 取餐口
        /// </summary>
        private void DoCoffeeQC(SimOrderData order)
        {
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_取咖啡出餐);
            Wait();
            LebaiRobot.GetInstance.SetValue(1);
            //订单状态改变：完成
            OrderChange(order.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COMPLETED_COOK);
            //SimpleFactory.GetInstance.OrderChanged(order.morkOrder.SuborderId,BPA.Message.Enum.ORDER_STATUS.COMPLETED_COOK);
            DeviceProcessLogShow($"{order.morkOrder.GoodsName}等待取餐");
            WaitTakeMealOrder.Enqueue(order);
        }

        /// <summary>
        /// 做冰淇淋
        /// </summary>
        private void DoIceCream(SimOrderData order)
        {
            //if (LebaiRobot.GetInstance.GetInput(3))
            //{
            //    MessageLog.GetInstance.Show("请擦拭冰淇淋机出口");
            //    return;
            //}

            #region 且时且多入场设备程序
            int checkeNum = 0;
            //are.Reset();
            LebaiRobot.GetInstance.SetValue(0);
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_取冰淇淋杯);
            Wait();
            new SCChip_TakeCupEvent() { Cup = IC_CUP.CUP_ICECREAM }.Publish();//落碗控制
            Thread.Sleep(500);
            MessageLog.GetInstance.Show("尝试取冰淇淋杯!");
            LebaiRobot.GetInstance.SetValue(1);

            int count = 2;
        p:
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_冰淇淋杯检测);
            Wait();

            LebaiRobot.GetInstance.SetValue(1);
            if (!LebaiRobot.GetInstance.GetInput())
            {
                if (count >= 3)
                {
                    //退出循环回到初始位置
                    MessageLog.GetInstance.Show($"执行{count}次取冰淇淋杯,仍未成功,订单默认废弃,机器人回到初始位置!");
                    LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_冰淇淋杯回原点);
                    Wait();
                    LebaiRobot.GetInstance.SetValue(1);
                    return;
                }
                MessageLog.GetInstance.Show($"执行{count}次取冰淇淋杯!");
                LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_二次取冰淇淋杯);
                new SCChip_TakeCupEvent() { Cup = IC_CUP.CUP_ICECREAM }.Publish();//落碗控制
                Wait();
                LebaiRobot.GetInstance.SetValue(1);
                count++;
                goto p;
            }
            MessageLog.GetInstance.Show("冰淇淋杯检测完成");

            #region 通讯冰淇淋机

            //制冷模式
            new GSIceCream_ModeSetEvent() { Mode = MORKI_MODE.制冷模式 }.Publish();
            LebaiRobot.GetInstance.SetValue(0);
            OrderChange(order.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COOKING);
            //SimpleFactory.GetInstance.OrderChanged(order.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COOKING);
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_接1号冰淇淋);
            Wait();
            bool doItResult = true;
            //出料
            new GSIceCream_DischargeEvent().Publish(delegate (object[] args)
            {
                doItResult = (bool)args[0];
            });
            if (doItResult)
            {
                IceCreamCookCheck();
            }
            else
            {
                int count_1 = 0;
                while (MorkIStatus.GetInstance().CXB <= 86)
                {
                    Thread.Sleep(5);
                    count_1++;
                    if (count_1 >= 2000)
                        break;
                }
                IceCreamCookCheck();
            }
            LebaiRobot.GetInstance.SetValue(1);
            #endregion

            while (LebaiRobot.GetInstance.GetInput())
            {
                Thread.Sleep(500);
            }
            LebaiRobot.GetInstance.Scene(LebaiRobot.SENCE_放冰淇淋位置);

            Wait();
            LebaiRobot.GetInstance.SetValue(1);
            //订单状态改变：完成
            OrderChange(order.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COMPLETED_COOK);
            //SimpleFactory.GetInstance.OrderChanged(order.morkOrder.SuborderId, BPA.Message.Enum.ORDER_STATUS.COMPLETED_COOK);
            MessageLog.GetInstance.Show($"{order.morkOrder.GoodsName}等待取餐");
            WaitTakeMealOrder.Enqueue(order);
            #endregion

        }

        /// <summary>
        /// 冰淇淋制作
        /// </summary>
        public void IceCreamCookCheck()
        {

            int retry = 3;
            DateTime beginTime = DateTime.Now;
            while (!LebaiRobot.GetInstance.GetInput(3))
            {
                if (retry <= 0 && DateTime.Now.Subtract(beginTime).TotalSeconds >= 10)
                {
                    MessageLog.GetInstance.Show("超时未出料，重试次数用尽");
                    break;
                }
                if (DateTime.Now.Subtract(beginTime).TotalSeconds > 5)
                {
                    MessageLog.GetInstance.Show("超时未出料，重新发送打料指令");
                    new GSIceCream_ModeSetEvent() { Mode = MORKI_MODE.打料 }.Publish();
                    beginTime = DateTime.Now;
                    retry--;
                }
                Thread.Sleep(10);
            }
            MessageLog.GetInstance.Show("开始等待6s");
            Thread.Sleep(5000);

        }

        //private void CoffeEndCookHandle(IEvent @event, EventBus.EventCallBackHandle callBack)
        //{
        //    //are.Set();
        //    if(MakeCoffeeOrder!=null)
        //        MakeCoffeeOrder.OrderStatus = 1;
        //}

        public void ReadRobotData()
        {
            ThreadManage.GetInstance().StartLong(new Action(() =>
            {
                lebai = LebaiRobot.GetInstance.GetValueAsync();
                LebaiRobot.GetInstance.GetRobotModeStatus();
                //LebaiRobot.GetInstance.GetInput();


                Thread.Sleep(100);
            }), "乐百机器人数据读取", true);
        }

        public void SimOrder<T>(T simOrder)
        {

        }

        /// <summary>
        /// IOT 广播消息命令
        /// </summary>
        public void IotBroadcast<T>(T broadcast)
        {
            if (broadcast != null && broadcast is IOTCommandModel iOTCommand)
            {
                switch (iOTCommand.CommandName)
                {
                    case 0://控制类
                        if (iOTCommand.CommandValue != null)
                        {
                            if (iOTCommand.CommandValue.ContainsKey("SimOrder"))
                            {
                                //SimOrder(new SimOrderData { NoodleLoc = 1, BowlLoc = 10 });
                            }
                        }
                        break;
                    case 1://设置属性

                        break;
                    case 2://通知消息

                        break;
                    default:
                        break;
                }
            }
        }

        public override void DoMain()
        {

        }

        public override void Stop()
        {
            
        }

        public override void ReadData()
        {
            
        }

        public override void MainTask()
        {
           
        }

        public override void ResetProgram()
        {
            
        }
    }


    public class SimOrderData
    {
        public string id { get; set; }

        public int OrderStatus { get; set; }

        public string Loc { get; set; }

        public MorkOrderPush morkOrder { get; set; }

        public SimOrderData()
        {
            id = Guid.NewGuid().ToString();
            OrderStatus = 0;
        }
    }
}
