using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
using WCS.BLL.Config;
using WCS.BLL.HardWare;
using WCS.BLL.Tool;
using WCS.DAL.Db;
using WCS.DAL.DbModels;

namespace WCS.BLL.Manager
{
    public static class TCPClientManager
    {
        /// <summary>
        /// 货架类型的TCP连接管理
        /// </summary>
        public static List<TCPClient> TCPClients = new List<TCPClient>();

        public static void InitTcpClient()
        {
            Logs.Write("【InitTcpClient】开始", LogsType.StartBoot);

            var clientsInDB = DbHelp.db.Queryable<ShelfInfo>()
                               .WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName), t => t.GroupName == LocalFile.Config.GroupName)
                               .Select(t => new
                               {
                                   IP = t.ClientIp,
                                   ShelfTypeName = t.ShelfTypeName,
                                   Port = t.Port,
                               })
                               .Distinct()
                               .ToList();
            Logs.Write($"【InitTcpClient】需要连接的服务端地址如下：\r\n{string.Join(";", clientsInDB)}", LogsType.StartBoot);
            foreach (var cleientInDB in clientsInDB)
            {
                Task.Run(() =>
                {
                    var tcpCleint = new TCPClient(cleientInDB.IP, cleientInDB.Port, cleientInDB.ShelfTypeName);
                    tcpCleint.tcpClient.Received += (client, e) =>
                    {
                        var clientIpHost = client.IP + ":" + client.Port;
                        var TcpCleint = TCPClientManager.GetTCPClientByIPHost(clientIpHost);
                        if (TcpCleint == null)
                        {
                            return EasyTask.CompletedTask;
                        }

                        var data = e.ByteBlock.Buffer.Take((int)e.ByteBlock.Length).ToArray();


                        Logs.Write($"【接收{clientIpHost}】{BitConverter.ToString(data)}", LogsType.Instructions);

                        e.ByteBlock.Clear();
                        var len = data.Length;

                        if (tcpCleint.ShelfTypeName == "信息化货架")
                        {
                            Logs.Write($"【信息化货架开始处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
                            Helper.ReturnDataProcess(TcpCleint, data);
                            Logs.Write($"【信息化货架完成处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
                            return EasyTask.CompletedTask;
                        }

                        if (tcpCleint.ShelfTypeName == "液晶货架")
                        {
                            Logs.Write($"【液晶货架开始处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
                            //Helper.ReturnDataProcess(TcpCleint, data);
                            Logs.Write($"【液晶货架完成处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
                            return EasyTask.CompletedTask;
                        }

                        for (int index = 0; index < data.Length - TcpCleint.PreFixLength; index++)
                        {
                            //协议拆包 通过前缀校验是否为完整数据包
                            var prefixInData = data.Skip(index).Take(TcpCleint.PreFixLength);
                            var isEqual = prefixInData.SequenceEqual(TcpCleint.Prefix);
                            if (isEqual)
                            {
                                var dataTemp = data.Skip(index).Take(TcpCleint.PreFixLength + TcpCleint.DataLength).ToArray();
                                if (dataTemp.Length < TcpCleint.PreFixLength + TcpCleint.DataLength)//拆包后不满足一条指令的长度
                                {
                                    continue;
                                }
                                Logs.Write($"【处理单条指令 开始】{BitConverter.ToString(dataTemp)}", LogsType.InstructionsProcess);
                                index += (TcpCleint.PreFixLength + TcpCleint.DataLength - 1);//每次循环index会+1 所以这里-1
                                                                                             //获取板子ID
                                var boardId = (dataTemp[TcpCleint.PreFixLength + 0] << 8) + dataTemp[TcpCleint.PreFixLength + 1];
                                var lightNumber = Convert.ToInt32(dataTemp[TcpCleint.PreFixLength + 3]);
                                //报警灯 返回来就修改对应的灯的颜色
                                if (dataTemp[TcpCleint.PreFixLength + 2] == 0x20)
                                {
                                    var shelf = ShelfManager.Shelves.Where(t => t.ClientIp == clientIpHost)
                                                                    .Where(t => t.LightId == boardId)
                                                                    .FirstOrDefault();
                                    var smartShelf = shelf as SmartShelf;
                                    smartShelf?.WarningLightProcess(dataTemp, boardId, lightNumber);
                                }
                                //!= 0x20  货架类型协议返回
                                else
                                {
                                    var shelf = ShelfManager.Shelves
                                                                  .Where(t => t.ClientIp == clientIpHost)
                                                                  .Where(t => t.ModuleIds != null && t.ModuleIds.Contains(boardId))
                                                                  .FirstOrDefault();
                                    var smartShelf = shelf as SmartShelf;
                                    smartShelf?.ProtocolProcess(dataTemp, boardId, lightNumber);
                                }
                                Logs.Write($"【处理单条指令 结束】{BitConverter.ToString(dataTemp)}", LogsType.InstructionsProcess);
                            }
                        }
                        return EasyTask.CompletedTask;
                    };
                    //配置首次连接后复位操作
                    tcpCleint.tcpClient.Connected += (client, e) =>
                    {
                        Logs.Write($"【TcpClient】{client.IP}完成连接,端口号{client.Port}", LogsType.StartBoot);
                        var clientIpHost = client.IP + ":" + client.Port;
                        var TcpCleint = TCPClientManager.GetTCPClientByIPHost(clientIpHost);
                        if (TcpCleint == null)
                        {
                            return EasyTask.CompletedTask;
                        }
                        //首次连接
                        if (TcpCleint.IsFirstConnected == false)
                        {
                            Logs.Write($"【InitTcpClient】{clientIpHost}完成首次连接", LogsType.StartBoot);



                            Console.WriteLine($"【InitTcpClient】{clientIpHost}完成首次连接");
                            InitStatus(TcpCleint);
                            TcpCleint.IsFirstConnected = true;
                            //获取剩余未完成连接的tcp
                            var noFirstConnectedTcps = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false)
                                                                                   .Select(t => t.RemoteIPHost)
                                                                                   .ToList();
                            Logs.Write($"【InitTcpClient】剩余未完成连接的TCP为{string.Join(";", noFirstConnectedTcps)}", LogsType.StartBoot);
                        }
                        return EasyTask.CompletedTask;
                    };

                    lock (TCPClients)//避免添加失败的情况
                    {
                        TCPClients.Add(tcpCleint);
                    }

                    tcpCleint.Connect();
                });
            }

            //启动线程监听所有TCP是否已经完成首次连接
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        Thread.Sleep(1000);
                        var noFirstConnectedClients = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false)
                                                                                 .ToList();
                        if (noFirstConnectedClients.Count == 0)
                        {
                            break;
                        }
                        else
                        {
                            Console.WriteLine($"存在tcp未完成首次连接，继续重连！");
                            noFirstConnectedClients.ForEach(t =>
                            {
                                t.ReConnectAsync();
                            });
                        }
                    }
                    catch (Exception ex)
                    {

                    }
                }
            });
            Logs.Write("【InitTcpClient】完成 后台继续连接", LogsType.StartBoot);
        }

        //后台启动时给所有板子、警示灯发送复位操作 保持状态一致
        public static void InitStatus()
        {
            Task.Run(() =>
            {
                try
                {
                    Thread.Sleep(1000);
                    //给所有板子发复位
                    TCPClients.ForEach(tcpClient =>
                    {
                        //板子复位
                        new SmartShelfModule()
                        {
                            BoardId = 2047
                        }.Reset(tcpClient);
                        //报警灯复位
                        new WarningLight().CloseLight(tcpClient);
                    });
                }
                catch (Exception ex)
                {
                    Logs.Write($"启动时复位异常，{ex.Message}");
                }
            });
        }

        //后台启动时给所有板子、警示灯发送复位操作 保持状态一致
        public static void InitStatus(TCPClient tcpClient)
        {
            var shelfInfo = DbHelp.db.Queryable<ShelfInfo>().Where(t => t.ClientIp == tcpClient.RemoteIPHost).ToList();
            if (shelfInfo.Count != 0)
            {
                if (shelfInfo[0].ShelfTypeName == "信息化货架")
                {
                    return;
                }
            }

            Task.Run(() =>
            {
                try
                {
                    Thread.Sleep(1000);

                    //板子复位
                    new SmartShelfModule()
                    {
                        BoardId = 2047
                    }.Reset(tcpClient);
                    //报警灯复位
                    new WarningLight().CloseLight(tcpClient);
                }
                catch (Exception ex)
                {
                    Logs.Write($"[{tcpClient.RemoteIPHost}]:启动时复位异常，{ex.Message}");
                }
            });
        }
        public static TCPClient GetTCPClientByIPHost(string IpHost)
        {
            return TCPClients.Where(t => t.RemoteIPHost == IpHost).FirstOrDefault();
        }
    }
}
