using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;
using BPA.Message;
using BPA.Utility;
using HBLConsole.Communication;
using HBLConsole.Factory;
using HBLConsole.GVL;
using HBLConsole.Interface;
using HBLConsole.Model;
using HBLConsole.Service;
using HBLDevice.Coffee;
using HBLDevice.IceCream;
using Robotc;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace HBLConsole.MORKIC
{
    /*
     * 冰淇淋咖啡机组合套装
     * 物料位置：
     * 1：冰淇料
     * 2：冰淇淋杯
     * 5：咖啡
     * 6：咖啡杯
     */
    public class Control_MORKIC : IControl
    {
        #region 单例模式
        private static Control_MORKIC _instance;
        public static Control_MORKIC Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Control_MORKIC();
                return _instance;
            }
        }
        public Control_MORKIC()
        {

        }
        #endregion
        GVL_MORIC mORKD = new GVL_MORIC();
        //咖啡机主控程序
        private CoffeeMachine coffeeMachine;
        //冰淇淋主控程序
        private IceCreamMachine iceCreamMachine;
        //物料存放位置
        private Dictionary<string, PolymerBatching> batchings = new Dictionary<string, PolymerBatching>();
        //容器位置
        private string holderLoc;
        //主料位置
        private string mainMaterialLoc;
        //子订单ID
        private string subOrderId;
        /// <summary>
        /// 获取乐百机器人的数据
        /// </summary>
        SignalResult lebai = new SignalResult();

        public void ConnectOk()
        {

        }
        public object GetT()
        {
            return mORKD;
        }


        ConcurrentQueue<MorkOrderPush> morkOrderPushes = new ConcurrentQueue<MorkOrderPush>();
        public void Init()
        {
            //构建所有商品物料信息
            batchings = PolymerBatching.BuildAll();

            EventBus.GetInstance().Subscribe<IceCreamEndCook>(IceCreamEndCookHandle);
            EventBus.GetInstance().Subscribe<CoffeEndCook>(CoffeEndCookHandle);

            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);
            if (iceCreamCXBThreshold > 0)
            {
                //设置冰淇淋成型比
                MorkIStatus.GetInstance().CXB_Threshold = (byte)iceCreamCXBThreshold;
            }
            //咖啡机创建
            coffeeMachine = new CoffeeMachine(com_Coffee, (BaudRates)Enum.Parse(typeof(BaudRates), baud_Coffee));
            //冰淇淋机创建
            iceCreamMachine = new IceCreamMachine(com_IceCream, (BaudRates)Enum.Parse(typeof(BaudRates), baud_IceCream));
            Main();
            ReadData();

            ThreadOperate.GetInstance.StartLong(new Action(() =>
            {
                while (morkOrderPushes.Count > 0)
                {
                    if (morkOrderPushes.TryDequeue(out MorkOrderPush order))
                    {
                        //商品类型
                        GOODS_TYPE currentGoodsType = GOODS_TYPE.NEITHER;
                        //子订单ID
                        subOrderId = order.SuborderId;
                        //遍历物料
                        foreach (var item in order.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:
                                        holderLoc = res.BatchingLoc;
                                        break;
                                    case BATCHING_CLASS.MAIN_MATERIAL:
                                        mainMaterialLoc = res.BatchingLoc;
                                        break;
                                }
                            }
                        }

                        //根据商品类型执行具体制作流程
                        switch (currentGoodsType)
                        {
                            case GOODS_TYPE.COFFEE:
                                DoCoffee();
                                break;
                            case GOODS_TYPE.ICECREAM:
                                DoIceCream();
                                break;
                        }
                    }
                }
                Thread.Sleep(1000);
            }), "订单制作");
        }



        public void DataParse<T>(T order)
        {
            if (order is MorkOrderPush morkOrderPush)
            {
                morkOrderPushes.Enqueue(morkOrderPush);
            }
        }

        /// <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 AutoResetEvent are = new AutoResetEvent(false);

        /// <summary>
        /// 做咖啡
        /// </summary>
        private void DoCoffee()
        {
            //订单状态改变：开始制作
            SimpleFactory.GetInstance.OrderChanged(subOrderId, BPA.Message.Enum.ORDER_STATUS.COOKING);
            //todo:先调用机器人

            ThreadOperate.GetInstance.Start(new Action(() => { LebaiHelper.GetInstance.Scene(10002); }), "调用乐百机器人做咖啡场景");

            while (!(lebai.Ok && lebai.Value == 2))
            {
                Thread.Sleep(5);
            }
            MessageLog.GetInstance.Show("机器人到达接咖啡口位置");
            new MakeCoffeeEvent() { DrinkCode = (DrCoffeeDrinksCode)int.Parse(mainMaterialLoc) }.Publish();
            are.WaitOne(1000 * 90);
            MessageLog.GetInstance.Show("咖啡机制作咖啡完成");
            LebaiHelper.GetInstance.SetValue(101);
            //订单状态改变：完成
            SimpleFactory.GetInstance.OrderChanged(subOrderId, BPA.Message.Enum.ORDER_STATUS.COMPLETED_COOK);
        }

        /// <summary>
        /// 做冰淇淋
        /// </summary>
        private void DoIceCream()
        {
            //订单状态改变：开始制作
            SimpleFactory.GetInstance.OrderChanged(subOrderId, BPA.Message.Enum.ORDER_STATUS.COOKING);
            //todo:先调用机器人
            ThreadOperate.GetInstance.Start(new Action(() => { LebaiHelper.GetInstance.Scene(10001); }), "调用乐百机器人做冰淇淋场景");

            while (!(lebai.Ok && lebai.Value == 1))
            {
                Thread.Sleep(5);
            }
            new DischargeEvent().Publish();

            //冰淇淋没有模式切换，强制等待10s
            Thread.Sleep(10000);
            LebaiHelper.GetInstance.SetValue(100);
            //are.WaitOne(100 * 90);
            //订单状态改变：完成
            SimpleFactory.GetInstance.OrderChanged(subOrderId, BPA.Message.Enum.ORDER_STATUS.COMPLETED_COOK);
        }

        private void CoffeEndCookHandle(IEvent @event, EventBus.EventCallBackHandle callBack)
        {
            are.Set();
        }

        private void IceCreamEndCookHandle(IEvent @event, EventBus.EventCallBackHandle callBack)
        {
            //are.Set();
        }


        public void Main()
        {
            //咖啡机开启主线程
            coffeeMachine.Start();
            //冰淇淋机开启主线程
            iceCreamMachine.Start();
            new ModeSetEvent() { Mode = MORKI_MODE.制冷模式 }.Publish();

            //开始心跳刷新，根据咖啡机及冰淇淋机来判断
            ThreadOperate.GetInstance.StartLong(new Action(() =>
            {
                //GeneralConfig.Healthy = true;
                GeneralConfig.Healthy =
                           LebaiHelper.GetInstance.IsConnected &&
                           MorkIStatus.GetInstance().CanDo &&
                           MorkCStatus.GetInstance().CanDo;
                Thread.Sleep(100);
            }), "MORK-IC心跳刷新");

        }


        public void ReadData()
        {
            ThreadOperate.GetInstance.StartLong(new Action(() =>
            {
                lebai = LebaiHelper.GetInstance.GetValueAsync();
                Debug.WriteLine(LebaiHelper.GetInstance.GetClawWdight());
                Thread.Sleep(100);
            }), "乐百机器人数据读取");
        }

        public void SimOrder<T>(T simOrder)
        {
            //ThreadOperate.GetInstance.Start(new Action(() =>
            //{
            //    DoIceCream();
            //    //DoCoffee();
            //}), "aaa");

        }
    }
}
