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;

namespace HBLConsole.MORKD
{
    public class Control_MORKD : IControl
    {
        #region 单例模式
        private static Control_MORKD _instance;
        public static Control_MORKD Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Control_MORKD();
                return _instance;
            }
        }
        public Control_MORKD()
        {

        }
        #endregion
        GVL_MORKD mORKD = new GVL_MORKD();
        public void ConnectOk()
        {
            Main();
            ReadData();
        }

        public object GetT()
        {
            return mORKD;
        }

        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 = loc, SuborderId = morkOrderPush.SuborderId });
                            }
                            else if (loc >= 11 && loc <= 12)
                            {
                                mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId });
                            }
                        }
                    }
                }
            }
        }

        public void Init()
        {
            ActionOperate.GetInstance.Register(new Action(() => { mORKD.InitControl(); }), "InitCommand");
        }

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

                TakeBowlTask();

                TakeNoodleTask();

                OutNoodleTask();

                SingleDetect();

                TurntableControl();

                OutSoupTask();

                TakeSoupTask();

                Thread.Sleep(100);

            }), "MainTask");
        }

        public void ReadData()
        {
            ModbusTcpHelper.GetInstance.Readbool(1120, 29, 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];
              }));


            ModbusTcpHelper.GetInstance.Readbool(1200, 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];
              }));
        }

        public void SimOrder<T>(T simOrder)
        {
            if (simOrder != null)
            {
                if (simOrder is SimOrderData simOrderData)
                {
                    string subId = Guid.NewGuid().ToString();
                    mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = simOrderData.NoodleLoc, SuborderId = subId });
                    mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = simOrderData.BowlLoc, SuborderId = subId });
                    mORKD.TakeSoupTask.Enqueue(new OrderLocInfo() { Loc = simOrderData.SoupLoc, SuborderId = subId });
                    MessageLog.GetInstance.Show($"添加订单：面条位置【{simOrderData.NoodleLoc}】,浇头位置【{simOrderData.SoupLoc}】,碗位置【{simOrderData.BowlLoc}】");
                }
            }
        }

        /// <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, orderLocInfo.Loc);
                            mORKD.AxisIdleLock[mORKD.AxisIdleLockIndex] = true;
                            MessageLog.GetInstance.Show($"执行取碗控制,位置:[{orderLocInfo.Loc}]");
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 转台控制
        /// </summary>
        private void TurntableControl()
        {
            if (mORKD.InitComplete && !mORKD.TurntableInterlock && !mORKD.AllowTakeNoodle && mORKD.RBTakeNoodleTask.Count > 0)
            {
                var result = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKD.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
                if (result != null)
                {
                    foreach (var item in result)
                    {
                        if (ushort.TryParse(item.BatchingLoc, out ushort loc))
                        {
                            if (!mORKD.TurntableLocLists.Contains(loc))
                            {
                                mORKD.TurntableStart(loc);
                                return;
                            }
                        }
                    }
                }
            }

            //转台到位检测
            if (RTrig.GetInstance("TurntableInPlace").Start(mORKD.TurntableInPlace))
            {
                if (mORKD.TurntableInterlock)
                {
                    if (mORKD.TurntableLowerLimit)
                    {
                        mORKD.TurntableLocLists.Clear();
                        mORKD.AllowTakeNoodle = true;
                    }
                    else
                    {
                        mORKD.TurntableInterlock = false;
                        mORKD.AllowTakeNoodle = 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);//查找煮面炉空闲位置
                    if (loc >= 0 && loc <= 5)
                    {
                        if (mORKD.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
                        {
                            mORKD.RBTakeNoodleStart((ushort)(loc + 1), orderLocInfo.Loc);
                            mORKD.CookNodelId[loc] = orderLocInfo.SuborderId;
                            SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
                            MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,煮面栏：[{loc + 1}]");
                            mORKD.TakeNoodleInterlock = true;
                        }
                    }
                }
            }

            //机器人取面完成信号检测
            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.CookNoodleCompleteTask.Enqueue(i);
                }
            }
            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.AxisIdleLock[index] = false;
                                mORKD.AxisAllowInvertedSoupID[index] = mORKD.AxisAllowInvertedNoodleID[index];
                                mORKD.AxisAllowInvertedNoodleID[index] = string.Empty;
                                MessageLog.GetInstance.Show($"从{loc + 1}号位置取面");
                                MessageLog.GetInstance.Show($"倒入{index + 1}号碗位置");
                            }
                        }
                    }
                }
            }
            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.SoupHeatCompleteID[index] = orderLocInfo.SuborderId;
                        mORKD.RBTakeSoupStart(orderLocInfo.Loc, (ushort)(index + 1));
                        SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
                    }
                }
            }

            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.SoupHeatCompleteID[i].Length > 0)
                        {
                            for (int m = 0; m < 2; m++)
                            {
                                if (mORKD.AxisAllowInvertedSoup[m] && mORKD.AxisAllowInvertedSoupID[m].Length > 0)
                                {
                                    if (mORKD.SoupHeatCompleteID[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.SoupHeatCompleteID[i] = string.Empty;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            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()
        {

        }
    }
}
