using System;
using HBLConsole.Interface;
using HBLConsole.Service;
using HBLConsole.Communication;
using BPA.Message;
using HBLConsole.Model;
using System.Linq;
using System.Threading;
using HBLConsole.Factory;
using BPA.Message.Enum;
using BPA.Message.IOT;
using System.Collections.Generic;
using System.Diagnostics;

namespace HBLConsole.MORKD
{
    public class Control_MORKD : IControl
    {
        GVL_MORKD mORKD = new GVL_MORKD();
        Alarm_MORKD alarm = new Alarm_MORKD();
        public void ConnectOk()
        {
            Main();
            ReadData();
            ResetProgram();
        }

        public void DataParse<T>(T order)
        {
            if (order is MorkOrderPush morkOrderPush)
            {
                foreach (var item in morkOrderPush.GoodBatchings)
                {
                    var res = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingId == item.BatchingId);
                    if (res != null)
                    {
                        if (ushort.TryParse(res.BatchingLoc, out ushort loc))
                        {
                            if (loc >= 1 && loc <= 5)
                            {
                                mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId, BatchingId = res.BatchingId });
                            }
                            else if (loc >= 6 && loc <= 10)
                            {
                                mORKD.TakeSoupTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(loc - 5), SuborderId = morkOrderPush.SuborderId });
                            }
                            else if (loc >= 11 && loc <= 12)
                            {
                                mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(loc - 10), SuborderId = morkOrderPush.SuborderId });
                            }
                        }
                    }
                }
            }
        }

        public void Init()
        {
            ActionManage.GetInstance.Register(new Action(() =>
            {
                mORKD.InitControl();

            }), "InitCommand");
        }

        bool Initing = false;

        /// <summary>
        /// 复位程序
        /// </summary>
        private void ResetProgram()
        {
            ThreadManage.GetInstance.StartLong(new Action(() =>
            {
                if (RTrig.GetInstance("ResetProgram").Start(Initing))
                {
                    ThreadManage.GetInstance.StopTask("MainTask", new Action(() =>
                     {
                         ThreadManage.GetInstance.StopTask("ReadPLCData", new Action(() =>
                         {
                             mORKD = null;
                             mORKD = new GVL_MORKD();
                             ActionManage.GetInstance.Send("ResetProgram");
                             ReadData();
                             Main();
                         }));
                     }));
                }

                Thread.Sleep(10);
            }), "ResetProgram");
        }

        public void Main()
        {
            ThreadManage.GetInstance.StartLong(new Action(() =>
            {
                mORKD.AllowRun = mORKD.InitComplete && !mORKD.TemperatureReached;

                TakeBowlTask();

                TakeNoodleTask();

                OutNoodleTask();

                SingleDetect();

                TurntableControl();

                OutSoupTask();

                TakeSoupTask();

                Thread.Sleep(10);

            }), "MainTask");
        }

        public void ReadData()
        {
            ThreadManage.GetInstance.StartLong(new Action(() =>
            {
                ModbusTcpHelper.GetInstance.Readbool(1120, 30, new Action<bool[]>((bools) =>
                {
                    mORKD.InitComplete = bools[0];
                    mORKD.TurntableInPlace = bools[1];
                    mORKD.RBTakeNoodleComplete = bools[2];

                    for (int i = 0; i < 2; i++)
                    {
                        mORKD.AxisIdle[i] = bools[3 + i];
                        mORKD.AxisAllowInvertedNoodle[i] = bools[5 + i];
                        mORKD.AxisAllowInvertedSoup[i] = bools[7 + i];
                        mORKD.SoupHeatComplete[i] = bools[9 + i];
                        mORKD.BreakMechanismIdle[i] = bools[25 + i];
                    }

                    for (int i = 0; i < 6; i++)
                    {
                        mORKD.CookNoodleBasketIdle[i] = bools[11 + i];
                        mORKD.CookNoodleComplete[i] = bools[17 + i];
                    }

                    mORKD.TakeNoodleRobotIdle = bools[23];
                    mORKD.TakeSoupRobotIdle = bools[24];
                    mORKD.TakeSoupComplete = bools[27];
                    mORKD.PutNoodleTakeMealComplete = bools[28];
                    Initing = bools[29];
                }));


                ModbusTcpHelper.GetInstance.Readbool(1280, 11, new Action<bool[]>((bools) =>
                {
                    mORKD.TurntableLowerLimit = bools[0];
                    mORKD.TurntableUpLimit = bools[1];
                    for (int i = 0; i < 5; i++)
                    {
                        mORKD.SoupMaterialShortage[i] = bools[2 + i];
                    }

                    for (int i = 0; i < 3; i++)
                    {
                        mORKD.OutMealDetect[i] = bools[7 + i];
                    }

                    mORKD.TemperatureReached = bools[10];
                }));

                var ResLoc = ModbusTcpHelper.GetInstance.Read(720, ReadType.HoldingRegisters);
                if (ResLoc != null)
                {
                    if (ResLoc is ushort loc)
                    {
                        mORKD.TurntableFeedbackloc = loc;
                    }
                }
                Thread.Sleep(100);
            }), "ReadPLCData");
        }

        public void SimOrder<T>(T simOrder)
        {
            if (simOrder != null)
            {
                if (simOrder is List<ushort> locs)
                {
                    string subId = Guid.NewGuid().ToString();
                    foreach (var item in locs)
                    {
                        if (item >= 1 && item <= 5)
                        {
                            //临时变量batchId
                            int tBatchId = item;
                            mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, BatchingId = tBatchId, SuborderId = subId });
                            MessageLog.GetInstance.Show($"添加订单：面条位置【{item}】");


                            //先注释，暂时不从服务器获取  2022.3.29
                            //BPA.Models.BatchingInfo res = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingLoc == item.ToString());
                            //if (res != null)
                            //{
                            //    mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, BatchingId = res.BatchingId, SuborderId = subId });
                            //    MessageLog.GetInstance.Show($"添加订单：面条位置【{item}】");
                            //}
                        }
                        if (item >= 6 && item <= 10)
                        {
                            mORKD.TakeSoupTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(item - 5), SuborderId = subId });
                            MessageLog.GetInstance.Show($"添加订单：浇头位置【{item}】");
                        }
                        if (item >= 11 && item <= 12)
                        {
                            mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(item - 10), SuborderId = subId });
                            MessageLog.GetInstance.Show($"添加订单：碗位置【{item - 10}】");
                        }
                    }
                }
            }
        }

        /// <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;
                }
            }
        }

        /// <summary>
        /// 取碗控制
        /// </summary>
        private void TakeBowlTask()
        {
            mORKD.AxisIdleIndex = mORKD.AxisIdle.GetIndex(true);
            mORKD.AxisIdleLockIndex = mORKD.AxisIdleLock.GetIndex(false);
            if (mORKD.AxisIdleLockIndex == mORKD.AxisIdleIndex)
            {
                if (mORKD.AxisIdleIndex >= 0 && mORKD.AxisIdleIndex <= 1)
                {
                    if (mORKD.AllowRun && mORKD.TakeBowlTask.Count > 0)
                    {
                        if (mORKD.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
                        {
                            mORKD.AxisAllowInvertedNoodleID[mORKD.AxisIdleIndex] = orderLocInfo.SuborderId;
                            mORKD.DropBowlStart((ushort)(mORKD.AxisIdleIndex + 1), orderLocInfo.Loc);
                            mORKD.AxisIdleLock[mORKD.AxisIdleLockIndex] = true;
                            MessageLog.GetInstance.Show($"执行取碗控制,碗位置:[{orderLocInfo.Loc}]，轴位置：[{mORKD.AxisIdleIndex + 1}]");
                            MessageLog.GetInstance.Show($"{mORKD.AxisIdleIndex + 1}号轴订单ID:[{orderLocInfo.SuborderId}]");
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 转台控制
        /// </summary>
        private void TurntableControl()
        {
            if (mORKD.TurntableInPlace && mORKD.InitComplete && !mORKD.AllowTakeNoodle && mORKD.RBTakeNoodleTask.Count > 0)
            {
                var result = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKD.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();

                if (mORKD.TurntableLowerLimit)
                {

                    if (mORKD.TurntableFeedbackloc == mORKD.RBTakeNoodleTask.ElementAt(0).Loc || (result?.Count > 0 && result?.Count == mORKD.TurntableLocLists.Count))
                    {
                        mORKD.TurntableLocLists.Clear();
                        mORKD.AllowTakeNoodle = true;
                        MessageLog.GetInstance.Show("转台位置OK,执行机器人取面");
                    }
                    else
                    {
                        if (!mORKD.TurntableInterlock)
                        {
                            mORKD.TurntableStart(mORKD.RBTakeNoodleTask.ElementAt(0).Loc);
                            MessageLog.GetInstance.Show($"有物料检测，反馈位置不同的转台启动控制，转台位置：[{mORKD.RBTakeNoodleTask.ElementAt(0).Loc}]");
                        }
                    }
                }
                else
                {
                    if (!mORKD.TurntableInterlock)
                    {


                        if (result != null)
                        {
                            foreach (var item in result)
                            {
                                if (ushort.TryParse(item.BatchingLoc, out ushort loc))
                                {
                                    if (mORKD.TurntableFeedbackloc != loc && !mORKD.TurntableLocLists.Contains(loc))
                                    {
                                        mORKD.TurntableStart(loc);
                                        MessageLog.GetInstance.Show($"没有物料检测的启动转台控制,转台位置：[{loc}]");
                                        break;
                                    }
                                    else if (mORKD.TurntableFeedbackloc == loc && !mORKD.TurntableLocLists.Contains(loc)) mORKD.TurntableLocLists.Add(loc);
                                }
                            }
                        }


                        //result?.ForEach(item =>
                        //{
                        //    if (ushort.TryParse(item.BatchingLoc, out ushort loc))
                        //    {
                        //        if (mORKD.TurntableFeedbackloc != loc && !mORKD.TurntableLocLists.Contains(loc))
                        //        {
                        //            mORKD.TurntableStart(loc);
                        //            MessageLog.GetInstance.Show($"没有物料检测的启动转台控制,转台位置：[{loc}]");
                        //            return;
                        //        }
                        //        else if (mORKD.TurntableFeedbackloc == loc) mORKD.TurntableLocLists.Add(loc);
                        //    }
                        //});
                    }

                }
            }

            //转台到位检测
            if (RTrig.GetInstance("TurntableInPlace").Start(mORKD.TurntableInPlace))
            {
                mORKD.TurntableInterlock = false;
            }
        }

        /// <summary>
        /// 取面任务
        /// </summary>
        private void TakeNoodleTask()
        {
            //取面控制
            if (mORKD.AllowRun && mORKD.TakeNoodleRobotIdle && !mORKD.RobotTaskInterlock && mORKD.AllowTakeNoodle)
            {
                if (mORKD.TurntableInPlace && !mORKD.OutNoodleing && mORKD.RBTakeNoodleTask.Count > 0)
                {
                    int loc = mORKD.CookNoodleBasketIdle.GetIndex(false);//查找煮面炉空闲位置
                    int IdleLoc = mORKD.CookNodeState.GetIndex(false);//获取煮面炉空闲状态互锁位置
                    if (loc >= 0 && loc <= 5)
                    {
                        if (mORKD.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
                        {
                            mORKD.RBTakeNoodleStart((ushort)(loc + 1), orderLocInfo.Loc);
                            mORKD.CookNodeState[loc] = true;
                            mORKD.CookNodelId[loc] = orderLocInfo.SuborderId;
                            SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
                            //MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,煮面栏：[{loc + 1}]");
                            mORKD.TakeNoodleInterlock = true;
                            MessageLog.GetInstance.Show($"{loc + 1}号煮面篮订单ID:[{orderLocInfo.SuborderId}]");
                        }
                    }
                }
            }

            //机器人取面完成信号检测
            if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKD.RBTakeNoodleComplete))
            {
                mORKD.TakeNoodleInterlock = false;
                mORKD.AllowTakeNoodle = false;
                MessageLog.GetInstance.Show("转台取面完成");
                mORKD.TakeNoodleCompleteReset();
            }
        }

        /// <summary>
        /// 出面控制
        /// </summary>
        private void OutNoodleTask()
        {
            for (ushort i = 0; i < 6; i++)
            {
                if (RTrig.GetInstance($"CookNoodleCompleteTask{i}").Start(mORKD.CookNoodleComplete[i] && mORKD.CookNodeState[i]))
                {
                    mORKD.CookNoodleCompleteTask.Enqueue(i);
                    MessageLog.GetInstance.Show($"{i + 1}号煮面口请求出面");
                }
            }
            if (mORKD.RobotTaskInterlock && !mORKD.TakeNoodleInterlock && mORKD.TakeNoodleRobotIdle)
            {
                if (mORKD.CookNoodleCompleteTask.Count > 0)
                {
                    string id = mORKD.CookNodelId[mORKD.CookNoodleCompleteTask.ElementAt(0)];
                    int index = mORKD.AxisAllowInvertedNoodleID.GetIndex(id);
                    if (index >= 0 && index <= 1)
                    {
                        if (mORKD.AxisAllowInvertedNoodle[index])
                        {
                            if (mORKD.CookNoodleCompleteTask.TryDequeue(out ushort loc))
                            {
                                mORKD.OutNoodleing = true;
                                mORKD.RBOutNoodleStart((ushort)(loc + 1), (ushort)(index + 1));
                                mORKD.CookNodeState[loc] = false;
                                mORKD.AxisIdleLock[index] = false;
                                mORKD.AxisAllowInvertedSoupID[index] = mORKD.AxisAllowInvertedNoodleID[index];
                                mORKD.AxisAllowInvertedNoodleID[index] = string.Empty;
                                MessageLog.GetInstance.Show($"从{loc + 1}号位置取面");
                                MessageLog.GetInstance.Show($"倒入{index + 1}号碗位置");
                                MessageLog.GetInstance.Show($"{index + 1}号轴允许倒浇头ID:[{  mORKD.AxisAllowInvertedSoupID[index]}]");
                            }
                        }
                    }
                }
            }
            int mlCount = mORKD.CookNoodleBasketIdle.Where(p => p == true).ToList().Count;
            mORKD.RobotTaskInterlock = mORKD.CookNoodleCompleteTask.Count > 0 && (mlCount >= 2 || mORKD.RBTakeNoodleTask.Count == 0);
        }

        /// <summary>
        /// 取浇头控制
        /// </summary>
        private void TakeSoupTask()
        {
            int index = mORKD.BreakMechanismIdle.GetIndex(true);
            if (index >= 0 && index <= 1)
            {
                if (mORKD.TakeSoupTask.Count > 0 && !mORKD.AllowTakeSoup && mORKD.TakeSoupRobotIdle && mORKD.AllowRun)
                {
                    if (mORKD.TakeSoupTask.TryDequeue(out OrderLocInfo orderLocInfo))
                    {
                        mORKD.SoupHeatLocID[index] = orderLocInfo.SuborderId;
                        mORKD.RBTakeSoupStart(orderLocInfo.Loc, (ushort)(index + 1));
                        SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
                        MessageLog.GetInstance.Show($"{index + 1}号浇头加热位ID:[{ mORKD.SoupHeatLocID[index]}]");
                    }
                }
            }

            if (RTrig.GetInstance("TakeSoupComplete").Start(mORKD.TakeSoupComplete))
            {
                mORKD.AllowTakeSoup = false;
                MessageLog.GetInstance.Show("取浇头完成");
                mORKD.TakeSoupCompleteReset();
            }
        }

        /// <summary>
        /// 浇头加热完成出浇头控制
        /// </summary>
        private void OutSoupTask()
        {
            if (!mORKD.AllowTakeSoup && !mORKD.AllowPutSoup && mORKD.TakeSoupRobotIdle)
            {
                mORKD.PutNoodleLoc = mORKD.OutMealDetect.GetIndex(false);
                if (mORKD.PutNoodleLoc >= 0 && mORKD.PutNoodleLoc <= 2)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        if (mORKD.SoupHeatComplete[i] && mORKD.SoupHeatLocID[i].Length > 0)
                        {
                            for (int m = 0; m < 2; m++)
                            {
                                if (mORKD.AxisAllowInvertedSoup[m] && mORKD.AxisAllowInvertedSoupID[m].Length > 0)
                                {
                                    if (mORKD.SoupHeatLocID[i] == mORKD.AxisAllowInvertedSoupID[m])
                                    {
                                        mORKD.HeatCompleteTakeSoupStart((ushort)(i + 1), (ushort)(m + 1), (ushort)(mORKD.PutNoodleLoc + 1));
                                        mORKD.OutMealId[mORKD.PutNoodleLoc] = mORKD.AxisAllowInvertedSoupID[m];
                                        mORKD.AxisAllowInvertedSoupID[m] = string.Empty;
                                        mORKD.SoupHeatLocID[i] = string.Empty;
                                        MessageLog.GetInstance.Show($"取浇头机器人往{m + 1}号轴到浇头");
                                        MessageLog.GetInstance.Show($"{mORKD.PutNoodleLoc + 1}号出餐口订单ID:[{ mORKD.OutMealId[mORKD.PutNoodleLoc]}]");
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (RTrig.GetInstance("PutNoodleTakeMealComplete").Start(mORKD.PutNoodleTakeMealComplete))
            {
                mORKD.AllowPutSoup = false;
                SimpleFactory.GetInstance.OrderChanged(mORKD.OutMealId[mORKD.PutNoodleLoc], ORDER_STATUS.COMPLETED_COOK);
                mORKD.PutNoodleTakeMealCompleteReset();
            }
        }

        /// <summary>
        /// 信号检测
        /// </summary>
        private void SingleDetect()
        {
            //取餐完成
            //var RemoveItem = Json<MorkOrderPushPar>.Data.morkOrderPushes.FirstOrDefault(p => p.OrderPush.SuborderId == "取餐口订单ID");
            //if (RemoveItem != null)
            //    Json<MorkOrderPushPar>.Data.morkOrderPushes.Remove(RemoveItem);

        }
    }
}
