using BPASmartClient.EventBus;
using BPASmartClient.Helper;
using BPASmartClient.Message;
using BPASmartClient.Model;
using BPASmartClient.Model.冰淇淋.Enum;
using BPASmartClient.Peripheral;
using BPASmartClient.SerialPort;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using static BPASmartClient.EventBus.EventBus;
using static BPASmartClient.GSIceCream.MessageDefine;

namespace BPASmartClient.GSIceCream
{
    public class IceCreamMachine :BasePeripheral
    {        
        //通讯代理
        SerialPortClient commProxy = null;
        //是否下发指令，主线程等待
        private bool free = false;
        //心跳指令
        private byte[] cmdHeartDW;
        //数据仓库
        private DataStorage<byte> dataStorage = new DataStorage<byte>();
        //串口COM口
        public string PortName { get; set; }
        //串口波特率
        public string BaudRate { get; set; }
        //心跳时间
        private DateTime lastRefreshTime = DateTime.MinValue;
        //是否在线
        public bool OnLine { get { return DateTime.Now.Subtract(lastRefreshTime).TotalSeconds <= 3; } }
        //private volatile static IceCreamMachine _Instance;
        //public static IceCreamMachine GetInstance => _Instance ?? (_Instance = new IceCreamMachine());
        public IceCreamMachine()
        {
            ICMSG_Heart_DW heartDW = new ICMSG_Heart_DW();
            cmdHeartDW = IcPack.StructureToByte(heartDW);
        }

        /// <summary>
        /// 主线程开始运行
        /// </summary>
        public override void Start()
        {
            try
            {
                commProxy.Start();
                IsConnected = true;
                free = false;
                MainLoop();
            }
            catch (Exception ex)
            {
                MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述：[{ex.Message}]");
            }
        }

        /// <summary>
        /// 停止运行
        /// </summary>
        public override void Stop()
        {
            try
            {
                commProxy.Stop();
                IsConnected = false;
                free = true;
            }
            catch (Exception ex)
            {
                MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述：[{ex.Message}]");
            }
        }

        private MSG_RESOLVE_STEP currentStep;
        private void MainLoop()
        {
            ThreadManage.GetInstance().StartLong(new Action(() =>
            {
                if (!free)
                {
                    commProxy.SendData(cmdHeartDW);
                }
                Thread.Sleep(500);
            }), "冰淇淋询问线程");

            ThreadManage.GetInstance().StartLong(new Action(() =>
            {
                ResolveMsg();
            }), "冰淇淋解析线程");
        }
        int contentLength = 0;
        int currentContentOffset = 0;
        private void ResolveMsg()
        {
            List<byte> temp = new List<byte>();
            //一系列解包
            while (dataStorage.GetSize() > 0)
            {
                byte item = dataStorage.GetData();
                switch (currentStep)
                {
                    case MSG_RESOLVE_STEP.NONE:
                        if (item == MessageDefine.HEADER1)
                        {
                            temp.Add(item);
                            currentStep = MSG_RESOLVE_STEP.HEADER1;
                            continue;
                        }
                        break;
                    case MSG_RESOLVE_STEP.HEADER1:
                        if (item == MessageDefine.HEADER2_UP)
                        {
                            temp.Add(item);
                            currentStep = MSG_RESOLVE_STEP.HEADER2;
                            continue;
                        }
                        else
                        {
                            temp.Clear();
                            currentStep = MSG_RESOLVE_STEP.NONE;
                            continue;
                        }
                    case MSG_RESOLVE_STEP.HEADER2:
                        switch ((IC_CMD)item)
                        {
                            case IC_CMD.HEART:
                                temp.Add(item);
                                contentLength = MessageDefine.MSG_LENGTH[(IC_CMD)item];
                                currentContentOffset = 0;
                                currentStep = MSG_RESOLVE_STEP.CMD;
                                break;
                            default:
                                temp.Clear();
                                currentStep = MSG_RESOLVE_STEP.NONE;
                                break;
                        }
                        break;
                }
                int retry = 3;
                while (dataStorage.GetSize() < contentLength + 2 && retry >= 0)
                {
                    retry--;
                    Thread.Sleep(100);
                }
                if (retry < 0)
                {
                    currentStep = MSG_RESOLVE_STEP.NONE;
                    currentContentOffset = 0;
                    contentLength = 0;
                    continue;
                }
                while (currentContentOffset < contentLength)
                {
                    item = dataStorage.GetData();
                    temp.Add(item);
                    currentContentOffset++;
                }

                retry = 3;
                while (dataStorage.GetSize() < 2 && retry >= 0)
                {
                    retry--;
                    Thread.Sleep(100);
                }
                temp.Add(dataStorage.GetData());
                temp.Add(dataStorage.GetData());
                ProcessMsg(temp.ToArray());
                currentStep = MSG_RESOLVE_STEP.NONE;
                continue;
            }
            Thread.Sleep(5);
        }

        private void ProcessHeart(ICMSG_Heart_UP heartUpMsg)
        {
            status["CurrentMode"] = heartUpMsg.MS;
            status["YLWD"]  = BitConverter.ToInt16(new byte[] { heartUpMsg.YLWD_L,heartUpMsg.YLWD_H },0);
            status["HQWD"]  = BitConverter.ToInt16(new byte[] { heartUpMsg.HQWD_L,heartUpMsg.HQWD_H },0);
            status["HJWD"]  = BitConverter.ToInt16(new byte[] { heartUpMsg.HJWD_L,heartUpMsg.HJWD_H },0);
            status["DL"]  = BitConverter.ToInt16(new byte[] { heartUpMsg.DL_L,heartUpMsg.DL_H },0);
            status["Fault"]  = (MORKI_FAULT)BitConverter.ToInt16(new byte[] { heartUpMsg.GZ_L,heartUpMsg.GZ_H },0);
            status["CXB"]  = heartUpMsg.CXB;
            status["DLCompleted"]  = (heartUpMsg.DLTJ >> 4 & 1) == 1;

            if (RTrig.GetInstance("打料完成检测").Start((bool)status["DLCompleted"]))
            {
                MessageLog.GetInstance.Show("打料完成");
            }

            if (RTrig.GetInstance("打料中检测").Start(!(bool)status["DLCompleted"]))
            {
                MessageLog.GetInstance.Show("打料中");
            }
        }

        private void ProcessModeUp(ICMSG_MODE_UP modeUpMsg)
        {
            MessageLog.GetInstance.Show(string.Format("模式返回为：{0}",modeUpMsg.Mode));
        }

        public void ProcessMsg(byte[] data)
        {
            lastRefreshTime = DateTime.Now;
            try
            {
                if (data.Length < 5)
                    return;
                switch (data[2])
                {
                    case (byte)IC_CMD.HEART:
                        var msg = IcPack.ByteToStructure<ICMSG_Heart_UP>(data.ToArray());
                        ProcessHeart(msg);
                        break;
                    case (byte)IC_CMD.MODE:
                        var modeUp = IcPack.ByteToStructure<ICMSG_MODE_UP>(data.ToArray());
                        ProcessModeUp(modeUp);
                        break;
                }
            }
            catch (Exception ex)
            {

            }
        }

        protected override void InitStatus()
        {
            status["YLWD"] = (short)0;
            status["HQWD"] = (short)0;
            status["HJWD"] = (short)0;
            status["DL"] = (short)0;
            status["DY"] = (short)0;
            status["CurrentMode"] = MORKI_MODE.待机模式;
            status["Fault"] = MORKI_FAULT.未发生故障;
            status["CXB"] = (byte)0;
            status["CXB_Threshold"] = (byte)0;
            status["DLCompleted"] = true;
        }

        public override void Init()
        {
            commProxy = new SerialPortClient(PortName,(BaudRates)Enum.Parse(typeof(BaudRates),BaudRate));
            commProxy.SetDataStorage(dataStorage);


            //广深冰淇淋机模式设置
            EventBus.EventBus.GetInstance().Subscribe<GSIceCream_ModeSetEvent>(DeviceId,delegate (IEvent @event,EventCallBackHandle callBack)
            {
                try
                {
                    free = true;
                    Thread.Sleep(200);
                    var data = IcPack.StructureToByte(ICMSG_MODE_DW.Build(((GSIceCream_ModeSetEvent)@event).Mode));
                    commProxy.SendData(data);
                    Thread.Sleep(200);
                    free = false;
                    MessageLog.GetInstance.Show(string.Format("设置模式[{0}]",Enum.GetName(typeof(MORKI_MODE),((GSIceCream_ModeSetEvent)@event).Mode)));
                }
                catch (Exception ex)
                {
                    MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述：[{ex.Message}]");
                }
            });

            //广深冰淇淋机打料
            EventBus.EventBus.GetInstance().Subscribe<GSIceCream_DischargeEvent>(DeviceId,delegate (IEvent @event,EventCallBackHandle callBack)
            {
                try
                {
                    if ((MORKI_FAULT)status["Fault"] != MORKI_FAULT.未发生故障)
                    {
                        MessageLog.GetInstance.Show(string.Format("当前存在故障[{0}%]，不允许制作",(MORKI_FAULT)status["Fault"]));
                        new GSIceCream_EndCookEvent() { DeviceId = DeviceId,Status = false }.Publish();
                        return;
                    }
                    if ((byte)status["CXB"] <= 86)
                    {
                        MessageLog.GetInstance.Show(string.Format("当前成型比[{0}%]，低于86%，不允许制作",(byte)status["CXB"]));
                        new GSIceCream_EndCookEvent() { DeviceId = DeviceId,Status = false }.Publish();
                        return;
                    }

                    bool modeRight = (MORKI_MODE)status["CurrentMode"] == MORKI_MODE.制冷模式;

                    if (!modeRight)
                    {
                        free = true;
                        Thread.Sleep(200);

                        var temp = IcPack.StructureToByte(ICMSG_MODE_DW.Build(MORKI_MODE.制冷模式));
                        commProxy.SendData(temp);

                        Thread.Sleep(200);
                        free = false;
                        MessageLog.GetInstance.Show(string.Format("出料操作->设置模式[{0}]",MORKI_MODE.制冷模式));

                        DateTime freeTime = DateTime.Now.AddSeconds(5);
                        while (DateTime.Now < freeTime)
                        {
                            Thread.Sleep(10);
                            modeRight = (MORKI_MODE)status["CurrentMode"] == MORKI_MODE.制冷模式;
                            if (modeRight)
                                break;
                        }
                    }

                    if (modeRight)
                    {
                        free = true;
                        Thread.Sleep(200);
                        var data = IcPack.StructureToByte(ICMSG_MODE_DW.Build(MORKI_MODE.打料));
                        commProxy.SendData(data);
                        Thread.Sleep(200);
                        free = false;
                        new GSIceCream_EndCookEvent() { DeviceId = DeviceId,Status =true}.Publish();
                        MessageLog.GetInstance.Show(string.Format("出料操作->设置模式[{0}]",MORKI_MODE.打料));
                    }
                    else
                    {
                        MessageLog.GetInstance.Show(string.Format("出料操作->模式切换失败，当前模式[{0}]，不允许出料",(MORKI_MODE)status["CurrentMode"]));
                        new GSIceCream_EndCookEvent() { DeviceId = DeviceId,Status = false }.Publish();
                    }
                }
                catch (Exception ex)
                {
                    MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述：[{ex.Message}]");
                }
            });
            InitStatus();
            //测试用
            Start();
        }
    }

}
