using Newtonsoft.Json.Linq;
using AssistClient.Device;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static AssistClient.Device.AxisDev;

namespace AssistClient
{
    public class DevContainer
    {
        public AxisDev devAxis;//=new AxisDev();
        public CodeScannerDev devCodeScanner;//= new CodeScannerDev(); 
        public IOCardDev devIOCard;//=new IOCardDev();
        public LightDev devLight;//=new LightDev(); 
        public ScannerDev devScannerCC;// = new ScannerDev(ScannerDev.ScannerType.CC); 
        public SizeLib libSize;
        public ForLib libFor;
        public IFLib libIF;

        public Action<WarningEnum, string> WarningEvent;

        public Action<bool, string> StateChange;
        public Action<string, string> OutDebugEvent;
        public Action<int, AxisPosType, double> axisPosEvent;
        public bool state = false;

        private Thread t;
        private IntPtr preView1, preView2;
        public void start(IntPtr view1, IntPtr view2)
        {
            this.preView1 = view1;
            this.preView2 = view2;

            devCodeScanner = new CodeScannerDev();
            devCodeScanner.WarningEvent = WarningEvent;
            if (!devCodeScanner.start()) throw new Exception("扫码枪初始化失败！");

            t = new System.Threading.Thread(run);
            t.IsBackground = true;
            t.Start();
        }
        public void stop()
        {
            try
            {
                state = false;
                try { devAxis.stop(); } catch { } 
                try { devIOCard.stop(); } catch { }
                try { devLight.stop(); } catch { } 
                try { devScannerCC.stop(); devScannerCC.close(); } catch { } 
                try { libSize.stop(); } catch { }
                try { devCodeScanner.stop(); } catch { }
            }
            catch { }
        }
        private void run()
        {
            try
            {
                //WarningEvent( WarningEnum.Normal, "启动1");
                devAxis = new AxisDev();
                devAxis.WarningEvent = WarningEvent; 
                devAxis.axisPosEvent = axisPosEvent;//位置POS 
                devIOCard = new IOCardDev();
                devIOCard.WarningEvent = WarningEvent;
                //devIOCard.OUTEvent = (index, data) =>
                //{
                //    if (Config.HeightDevIOState && devAxis.IsInit && (devAxis.isMoveing(0) || devAxis.isMoveing(2)))
                //    {
                //        WarningEvent?.Invoke(WarningEnum.High, "厚度IO已打开，急停，请检查设备，防止损坏！");
                //        //devAxis.stopNow();
                //    }
                //};
                devLight = new LightDev();
                devLight.WarningEvent = WarningEvent; 
                devScannerCC = new ScannerDev(ScannerDev.ScannerType.CC);
                devScannerCC.WarningEvent = WarningEvent;
                //WarningEvent(WarningEnum.Normal, "启动2");
                libSize = new SizeLib();
                //WarningEvent(WarningEnum.Normal, "启动2.5");
                libSize.WarningEvent = WarningEvent;
                libFor = new ForLib();
                libIF = new IFLib();
                //WarningEvent(WarningEnum.Normal, "启动3");
                //启动
                if (!devAxis.start(Config.Axis_PulseOutMode)) throw new Exception("运动板卡初始化失败！");
                //if (!devCodeScanner.start()) throw new Exception("扫码枪初始化失败！");
                if (!devIOCard.start(Config.IOCard_DeviceNum)) throw new Exception("I/O板卡初始化失败！");
                if (!Config.SkipLight && !devLight.start(Config.Light_PortNum)) throw new Exception("光源设备初始化失败！");
                 
                if (!Config.SkipScannerCC && !devScannerCC.open()) throw new Exception("相机初始化失败！");
                if (!Config.SkipScannerCC && !devScannerCC.start(this.preView2, Config.SizeBmp_Path)) throw new Exception("相机打开失败！");

                //WarningEvent(WarningEnum.Normal, "启动4");
                if (!libSize.start(Config.SizeEnginePath)) throw new Exception("尺寸库初始化失败！");
                //WarningEvent(WarningEnum.Normal, "启动5");
                //
                state = true;
                StateChange?.Invoke(true, "成功");
            }
            catch (Exception ex)
            {
                stop();
                StateChange?.Invoke(false, ex.Message);
            }
        }

        /// <summary>
        /// I/O指令输出
        /// </summary>
        /// <param name="key">CMDName</param>
        /// <param name="isStrobe">频闪</param>
        /// <param name="recover">输出sleep下，后恢复原信号</param>
        /// <param name="recoverWaitTime">sleep多久后反转</param>
        /// <returns></returns>
        public bool io_output(CMDName key, bool isStrobe = false, bool recover = false, int recoverWaitTime = 100)
        {
            if (Config.CMDProcess.ContainsKey(key))
                return io_output(key.ToString(),Config.CMDProcess[key], isStrobe, recover, recoverWaitTime);
            return false;
        }
        /// <summary>
        /// I/O指令输出
        /// </summary>
        /// <param name="processParam"></param>
        /// <param name="isStrobe">频闪</param>
        /// <param name="recover">输出sleep(recoverWaitTime)下，后恢复原信号</param>
        /// <param name="recoverWaitTime">sleep 后反转</param>
        public bool io_output(string tagName,JObject processParam, bool isStrobe = false, bool recover = false, int recoverWaitTime = 100)
        {
            bool result = false;
            string[] OUT_OP_SHOW = processParam.Value<JArray>("OUT_OP_SHOW").ToObject<List<string>>().ToArray();
            OUT_OP_SHOW = Utils.Util.IODataFormatBinaryStr(OUT_OP_SHOW, true);
            for (int i = 0; i < OUT_OP_SHOW.Length; i++)
            {
                for (int j = 0; j < OUT_OP_SHOW[i].Length; j++)
                {
                    int jj = OUT_OP_SHOW[i].Length - j - 1;
                    if (OUT_OP_SHOW[i][jj] == 'L' || OUT_OP_SHOW[i][jj] == 'H')
                    { 
                        if (recover)
                        {
                            if (recoverWaitTime > 0)
                            {
                                OutDebugEvent?.Invoke(tagName, $"向I/O输出引脚{i}-{j},信号{OUT_OP_SHOW[i][jj]},输出时长:{recoverWaitTime}ms");
                                devIOCard.writeBitState(i, j, OUT_OP_SHOW[i][jj] == 'H', isStrobe);
                                Thread.Sleep(recoverWaitTime);
                            }
                            OutDebugEvent?.Invoke(tagName, $"向I/O输出引脚{i}-{j},信号{OUT_OP_SHOW[i][jj]=='L'}");
                            devIOCard.writeBitState(i, j, OUT_OP_SHOW[i][jj] == 'L');
                        }
                        else
                        {
                            OutDebugEvent?.Invoke(tagName, $"向I/O输出引脚{i}-{j},信号{OUT_OP_SHOW[i][jj]}");
                            devIOCard.writeBitState(i, j, OUT_OP_SHOW[i][jj] == 'H', isStrobe);
                        }
                        result = true;
                    }
                }
            }

            return result;
        }
    }
}
