using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using WCS.BLL.Config;
using WCS.DAL.Db;
using WCS.DAL.DbModels;

namespace WCS.BLL.HardWare
{
    public class SmartShelfModule : IModuleBase
    {
        #region 协议
        /// <summary>
        /// 进入入库模式
        /// </summary>
        public byte[] GoInInstoreData = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 确认入库
        /// </summary>
        public byte[] ComfirmInstoreData = { 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        public byte[] ComfirmErrInstoreData = { 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 退出入库模式
        /// </summary>
        public byte[] GoOutInstoreData = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 自检模式
        /// </summary>
        public byte[] CheckModeData = { 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 进入出库模式
        /// </summary>
        public byte[] GoInOutstoreModeData = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 };

        /// <summary>
        /// 确认出库信号
        /// </summary>
        public byte[] ComfirmOutstoreData = { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        /// <summary>
        /// 退出出库模式
        /// </summary>
        public byte[] GoOutOutstoreModeData = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 进入盘点模式
        /// 04代表颜色为蓝色色
        /// </summary>
        public byte[] GoInStockTakingModeData = { 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 };
        /// <summary>
        /// 确认盘点
        /// 03代表颜色为黄色
        /// </summary>
        public byte[] ConfirmStockTakingData = { 0x09, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 退出盘点模式
        /// </summary>
        public byte[] GoOutStockTakingModeData = { 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 复位命令
        /// </summary>
        public byte[] ResetData = { 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        /// <summary>
        /// 查询当前电压值
        /// </summary>
        public byte[] VoltageSingleData = { 0x17, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        /// <summary>
        /// 查询电压偏移值
        /// </summary>
        public byte[] OffsetSingleData = { 0x18, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        /// <summary>
        /// 查询电压标准值
        /// </summary>
        public byte[] StandardSingleData = { 0x19, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        /// <summary>
        /// 标定
        /// </summary>
        public byte[] CalibrationData = { 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        /// <summary>
        /// 设置偏移量  01 F4 = 500
        /// </summary>
        public byte[] SetOffsetData = { 0x0E, 0x0A, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x00 };

        #endregion
        public int ModuleId { get; set; }
        public string ModuleCode { get; set; }
        public int BoardId { get; set; }
        public bool IsEnable { get; set; }
        public Mode CurrentMode { get; set; }
        /// <summary>
        /// 是否已发送自检命令
        /// </summary>
        public bool IsSelfCheck { get; set; } = false;
        public List<string> CurrentOutSns { get; set; }
        public List<string> CurrentStockTakingSns { get; set; }

        public void SetCurrentMode()
        {

        }

        public void GoInInstoreMode(TCPClient tcpClient)
        {
            if (CurrentMode != Mode.待机模式)
            {
                //TO DO 退出对应的模式 然后再发送进入入库模式
            }
            var storeInfos = DbHelp.db.Queryable<StoreInfo>()
                                     .Where(t => t.ModuleId == ModuleId)
                                     .Where(t => t.BoardId == BoardId)
                                     .OrderBy(t => t.LightNumber)
                                     .ToList();
            char[] data = "0000000000000000".ToCharArray();
            
            //禁用
            char[] dataBan = "0000000000000000".ToCharArray();

            var boardStoreNumber = storeInfos.Count();
            foreach (var storeInfo in storeInfos)
            {
                if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn) && storeInfo.LightNumber > 0 && storeInfo.LightNumber <= boardStoreNumber)
                {
                    data[storeInfo.LightNumber - 1] = '1';

                    //禁用
                    if (storeInfo.CurrentMatSn == "禁用")
                    {
                        dataBan[storeInfo.LightNumber - 1] = '1';
                    }
                }
            }
            var dataStr = string.Join("", data.Reverse());
            var data1 = dataStr.Substring(8, 8);
            var data2 = dataStr.Substring(0, 8);
            GoInInstoreData[1] = Convert.ToByte(data1, 2);
            GoInInstoreData[2] = Convert.ToByte(data2, 2);

            //禁用
            var dataBanStr = string.Join("", dataBan.Reverse());
            var data1Ban = dataBanStr.Substring(8, 8);
            var data2Ban = dataBanStr.Substring(0, 8);
            GoInInstoreData[6] = Convert.ToByte(data1Ban, 2);
            GoInInstoreData[7] = Convert.ToByte(data2Ban, 2);

            tcpClient.Send(tcpClient.GenerateMessage(BoardId, GoInInstoreData));
        }

        public void ComfirmInstore(TCPClient tcpClient)
        {
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, ComfirmInstoreData));
        }

        public void ComfirmErrInstore(TCPClient tcpClient)
        {
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, ComfirmErrInstoreData));
        }

        public void GoOutInstoreMode(TCPClient tcpClient)
        {
            if (CurrentMode == Mode.入库模式)
            {
                tcpClient.Send(tcpClient.GenerateMessage(BoardId, GoOutInstoreData));
            }
            else
            {
                //这里应该是状态异常的 正常不会是这种状态
                Reset(tcpClient);
            }
        }

        /// <summary>
        /// 复位
        /// </summary>
        /// <param name="tcpClient"></param>
        public void Reset(TCPClient tcpClient)
        {
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, ResetData));
        }

        /// <summary>
        /// 自检
        /// </summary>
        /// <param name="tcpClient"></param>
        public void ShelfCheck(TCPClient tcpClient)
        {
            if (CurrentMode != Mode.待机模式)
            {
                return;
            }
            var storeInfos = DbHelp.db.Queryable<StoreInfo>()
                                                 .Where(t => t.ModuleId == ModuleId)
                                                 .Where(t => t.BoardId == BoardId)
                                                 .OrderBy(t => t.LightNumber)
                                                 .ToList();
            char[] data = "0000000000000000".ToCharArray();
            //禁用功能
            char[] dataBan = "0000000000000000".ToCharArray();

            var boardStoreNumber = storeInfos.Count();
            foreach (var storeInfo in storeInfos)
            {
                if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn) && storeInfo.LightNumber > 0 && storeInfo.LightNumber <= boardStoreNumber)
                {
                    data[storeInfo.LightNumber - 1] = '1';

                    //禁用功能
                    if (storeInfo.CurrentMatSn == "禁用")
                    {
                        dataBan[storeInfo.LightNumber - 1] = '1';
                    }
                }
            }
            var dataStr = string.Join("", data.Reverse());
            var data1 = dataStr.Substring(8, 8);
            var data2 = dataStr.Substring(0, 8);
            CheckModeData[1] = Convert.ToByte(data1, 2);
            CheckModeData[2] = Convert.ToByte(data2, 2);

            //禁用功能
            var dataBanStr = string.Join("", dataBan.Reverse());
            var data1Ban = dataBanStr.Substring(8, 8);
            var data2Ban = dataBanStr.Substring(0, 8);
            CheckModeData[6] = Convert.ToByte(data1Ban, 2);
            CheckModeData[7] = Convert.ToByte(data2Ban, 2);

            tcpClient.Send(tcpClient.GenerateMessage(BoardId, CheckModeData));
        }

        /// <summary>
        /// 进入出库模式、亮灯
        /// </summary>
        /// <param name="tcpClient"></param>
        public void GoInOutStoreMode(TCPClient tcpClient, List<string> outSns)
        {
            Logs.Write($"模组{ModuleCode}，本次亮灯物料{string.Join(",", outSns)}", LogsType.Outstore);
            CurrentOutSns = outSns;
            var storeInfos = DbHelp.db.Queryable<StoreInfo>().Where(t => t.ModuleId == ModuleId)
                                      .Where(t => t.BoardId == BoardId)
                                      .OrderBy(t => t.LightNumber)
                                      .ToList();
            //计算物料在库的库位
            char[] data = "0000000000000000".ToCharArray();

            //计算禁用的库位
            char[] dataBan = "0000000000000000".ToCharArray();

            var storeNumber = storeInfos.Count();
            foreach (var storeInfo in storeInfos)
            {
                if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn) && storeInfo.LightNumber > 0 && storeInfo.LightNumber <= storeNumber)
                {
                    data[storeInfo.LightNumber - 1] = '1';
                    //禁用
                    if (storeInfo.CurrentMatSn == "禁用")
                    {
                        dataBan[storeInfo.LightNumber - 1] = '1';
                    }
                }
            }
            var dataStr = string.Join("", data.Reverse());
            var data1 = dataStr.Substring(8, 8);
            var data2 = dataStr.Substring(0, 8);
            GoInOutstoreModeData[1] = Convert.ToByte(data1, 2);
            GoInOutstoreModeData[2] = Convert.ToByte(data2, 2);

            //禁用
            var dataBanStr = string.Join("", dataBan.Reverse());
            var data1Ban = dataBanStr.Substring(8, 8);
            var data2Ban = dataBanStr.Substring(0, 8);
            GoInOutstoreModeData[6] = Convert.ToByte(data1Ban, 2);
            GoInOutstoreModeData[7] = Convert.ToByte(data2Ban, 2);

            //出库位置亮灯
            if (outSns != null && outSns.Count > 0)
            {
                var outStoreInfos = storeInfos.Where(t => outSns.Contains(t.CurrentMatSn))
                                              .ToList();
                char[] outData = "0000000000000000".ToCharArray();
                foreach (var storeInfo in outStoreInfos)
                {
                    if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn) && storeInfo.LightNumber > 0 && storeInfo.LightNumber <= storeNumber)
                    {
                        outData[storeInfo.LightNumber - 1] = '1';
                    }
                }
                var outDataStr = string.Join("", outData.Reverse());
                var data3 = outDataStr.Substring(8, 8);
                var data4 = outDataStr.Substring(0, 8);
                GoInOutstoreModeData[3] = Convert.ToByte(data3, 2);
                GoInOutstoreModeData[4] = Convert.ToByte(data4, 2);

                if (LocalFile.Config.IsSameMatCodeOut)
                {
                    GoInOutstoreModeData[5] = LocalStatic.CurrentOutStoreColor;
                }
                else
                {
                    GoInOutstoreModeData[5] = 0x02;
                }
            }
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, GoInOutstoreModeData));
        }
        public void ComfirmOutstore(TCPClient tcpClient, byte lightNumber)
        {
            ComfirmOutstoreData[1] = lightNumber;
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, ComfirmOutstoreData));
        }
        /// <summary>
        /// 退出出库模式
        /// </summary>
        /// <param name="tcpClient"></param>
        public void GoOutOutStoreMode(TCPClient tcpClient)
        {
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, GoOutOutstoreModeData));
        }

        /// <summary>
        /// 未盘点的物料进入盘点模式、亮灯
        /// </summary>
        /// <param name="tcpClient"></param>
        public void GoInStockTakingMode(TCPClient tcpClient, List<string> stockTakingSns)
        {
            CurrentStockTakingSns = stockTakingSns;

            var storeInfos = DbHelp.db.Queryable<StoreInfo>().Where(t => t.ModuleId == ModuleId)
                                      .Where(t => t.BoardId == BoardId)
                                      .OrderBy(t => t.LightNumber)
                                      .ToList();
            //计算物料在库的库位
            char[] data = "0000000000000000".ToCharArray();
            var storeNumber = storeInfos.Count();

            char[] outData = "0000000000000000".ToCharArray();
            //盘点位置亮灯
            if (stockTakingSns != null && stockTakingSns.Count > 0)
            {
                var outStoreInfos = storeInfos.Where(t => stockTakingSns.Contains(t.CurrentMatSn))
                                              .ToList();
                foreach (var storeInfo in outStoreInfos)
                {
                    if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn) && storeInfo.LightNumber > 0 && storeInfo.LightNumber <= storeNumber)
                    {
                        outData[storeInfo.LightNumber - 1] = '1';
                    }
                }
            }
            var outDataStr = string.Join("", outData.Reverse());
            var data3 = outDataStr.Substring(8, 8);
            var data4 = outDataStr.Substring(0, 8);
            GoInStockTakingModeData[2] = Convert.ToByte(data3, 2);
            GoInStockTakingModeData[3] = Convert.ToByte(data4, 2);

            tcpClient.Send(tcpClient.GenerateMessage(BoardId, GoInStockTakingModeData));
        }

        /// <summary>
        /// 已确认过的物料
        /// </summary>
        /// <param name="tcpClient"></param>
        public void ConfirmStockTaking(TCPClient tcpClient, List<string> stockTakingSns)
        {
            CurrentStockTakingSns = stockTakingSns;

            var storeInfos = DbHelp.db.Queryable<StoreInfo>().Where(t => t.ModuleId == ModuleId)
                                      .Where(t => t.BoardId == BoardId)
                                      .OrderBy(t => t.LightNumber)
                                      .ToList();
            //计算物料在库的库位
            char[] data = "0000000000000000".ToCharArray();
            var storeNumber = storeInfos.Count();

            char[] outData = "0000000000000000".ToCharArray();
            //盘点位置亮灯
            if (stockTakingSns != null && stockTakingSns.Count > 0)
            {
                var outStoreInfos = storeInfos.Where(t => stockTakingSns.Contains(t.CurrentMatSn))
                                              .ToList();
                foreach (var storeInfo in outStoreInfos)
                {
                    if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn) && storeInfo.LightNumber > 0 && storeInfo.LightNumber <= storeNumber)
                    {
                        outData[storeInfo.LightNumber - 1] = '1';
                    }
                }
            }

            var outDataStr = string.Join("", outData.Reverse());
            var data3 = outDataStr.Substring(8, 8);
            var data4 = outDataStr.Substring(0, 8);
            ConfirmStockTakingData[2] = Convert.ToByte(data3, 2);
            ConfirmStockTakingData[3] = Convert.ToByte(data4, 2);

            tcpClient.Send(tcpClient.GenerateMessage(BoardId, ConfirmStockTakingData));
        }

        /// <summary>
        /// 单个确认物料
        /// </summary>
        /// <param name="tcpClient"></param>
        public void ConfirmStockTakingSingle(TCPClient tcpClient, int lightNumber)
        {
            var storeInfos = DbHelp.db.Queryable<StoreInfo>().Where(t => t.ModuleId == ModuleId)
                                      .Where(t => t.BoardId == BoardId)
                                      .OrderBy(t => t.LightNumber)
                                      .ToList();
            //计算物料在库的库位
            char[] data = "0000000000000000".ToCharArray();
            var storeNumber = storeInfos.Count();

            //盘点位置亮灯
            var outStoreInfos = storeInfos.Where(t => t.LightNumber == lightNumber)
                                          .ToList();
            char[] outData = "0000000000000000".ToCharArray();
            foreach (var storeInfo in outStoreInfos)
            {
                if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn) && storeInfo.LightNumber > 0 && storeInfo.LightNumber <= storeNumber)
                {
                    outData[storeInfo.LightNumber - 1] = '1';
                }
            }
            var outDataStr = string.Join("", outData.Reverse());
            var data3 = outDataStr.Substring(8, 8);
            var data4 = outDataStr.Substring(0, 8);
            ConfirmStockTakingData[2] = Convert.ToByte(data3, 2);
            ConfirmStockTakingData[3] = Convert.ToByte(data4, 2);

            tcpClient.Send(tcpClient.GenerateMessage(BoardId, ConfirmStockTakingData));
        }


        /// <summary>
        /// 退出盘点模式
        /// </summary>
        /// <param name="tcpClient"></param>
        public void GoOutStockTakingMode(TCPClient tcpClient)
        {
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, GoOutStockTakingModeData));
        }

        public void ComfirmStockTaking(TCPClient tcpClient, byte lightNumber)
        {
            ComfirmOutstoreData[1] = lightNumber;
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, ComfirmOutstoreData));
        }

        /// <summary>
        /// 查询电压值
        /// </summary>
        /// <param name="tcpClient"></param>
        public void QueryVoltage(TCPClient tcpClient)
        {
            Thread.Sleep(10);
            Task.Run(() =>
            {
                tcpClient.Send(tcpClient.GenerateMessage(BoardId, VoltageSingleData));
                Thread.Sleep(50);
                tcpClient.Send(tcpClient.GenerateMessage(BoardId, StandardSingleData));
                Thread.Sleep(50);
                tcpClient.Send(tcpClient.GenerateMessage(BoardId, OffsetSingleData));
            });
        }

        public void CalibrationSetOffset(int offSet, TCPClient tcpClient)
        {
            var offSetData = BitConverter.GetBytes(unchecked((short)offSet));
            // 检查是否需要交换字节  
            if (BitConverter.IsLittleEndian)
            {
                // 如果是小端序系统，则交换字节  
                byte temp = offSetData[0];
                offSetData[0] = offSetData[1];
                offSetData[1] = temp;
            }

            SetOffsetData[2] = offSetData[0];
            SetOffsetData[3] = offSetData[1];

            tcpClient.Send(tcpClient.GenerateMessage(BoardId, CalibrationData));
            Thread.Sleep(100);
            tcpClient.Send(tcpClient.GenerateMessage(BoardId, SetOffsetData));
        }
    }
}
