using Serilog;
using SlnMesnac.Common;
using SlnMesnac.Model.dto;
using SlnMesnac.Model.Enum;
using SlnMesnac.Serilog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;

#region << 版 本 注 释 >>

/*--------------------------------------------------------------------
* 版权所有 (c) 2024 WenJY 保留所有权利。
* CLR版本：4.0.30319.42000
* 机器名称：LAPTOP-E0N2L34V
* 命名空间：SlnMesnac.TouchSocket
* 唯一标识：496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
*
* 创建者：WenJY
* 电子邮箱：wenjy@mesnac.com
* 创建时间：2024-03-27 21:58:35
* 版本：V1.0.0
* 描述：
*
*--------------------------------------------------------------------
* 修改人：
* 时间：
* 修改说明：
*
* 版本：V1.0.0
*--------------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

namespace SlnMesnac.TouchSocket
{
    public class TcpServer
    {
        private SerilogHelper _logger;
        private readonly TcpService _service;


        /// <summary>
        /// 接收客户端指令委托
        /// </summary>
        public delegate void ReceivedClientBuffer(byte[] buffer);

        public event ReceivedClientBuffer? ReceivedClientBufferEvent;

        public delegate void RefreshClientInfo(TcpService tcpService);

        public event RefreshClientInfo? RefreshClientInfoEvent;


        private StringChange _stringChange;

        public TcpServer(SerilogHelper logger, StringChange stringChange, TcpService tcpService)
        {
            _logger = logger;
            _service = tcpService;
            _stringChange = stringChange;
        }
        public void Init(int serverPort)
        {
            try
            {
                _service.Connecting = (client, e) =>
                {
                    Log.Information($"客户端{client.IP}正在接入服务");
                    if (!client.IsClient)
                    {
                        e.Id = $"{client.IP}:{client.Port}";
                    }
                    return EasyTask.CompletedTask;
                };
                _service.Connected = (client, e) =>
                {
                    Log.Information($"客户端{client.IP}接入服务成功");
                    RefreshClientInfoEvent?.Invoke(_service);
                    return EasyTask.CompletedTask;
                };
                _service.Closed = (client, e) =>
                {
                    Log.Information($"客户端{client.IP}断开连接");
                    RefreshClientInfoEvent?.Invoke(_service);
                    return EasyTask.CompletedTask;
                };
                _service.Received = (client, e) =>
                {
                    //从客户端收到信息
                    //var mes = Encoding.UTF8.GetString(e.Memory.Span.ToArray(), 0, e.Memory.Span.Length);//注意：数据长度是byteBlock.Len

                    byte[] receivedBuffer = new byte[e.Memory.Span.Length];
                    Array.Copy(e.Memory.Span.ToArray(), 0, receivedBuffer, 0, e.Memory.Span.Length);
                    //MES客户端消息解析
                    if (receivedBuffer[4] == 0x65)
                    {
                        byte[] addrby = new byte[2];
                        Array.Copy(receivedBuffer, 1, addrby, 0, 2);
                        var flag = BitConverter.ToUInt16(addrby, 0);
                        _service.ResetIdAsync($"{client.IP}:{client.Port}", flag.ToString());
                    }


                    //ReceivedClientBufferEvent?.Invoke(receivedBuffer);
                    return EasyTask.CompletedTask;
                };

                _service.SetupAsync(new TouchSocketConfig()//载入配置
                    .SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })
                    .ConfigureContainer(a =>//容器的配置顺序应该在最前面
                    {
                        a.AddConsoleLogger();
                    })
                    .ConfigurePlugins(a =>
                    {
                        //自定义插件
                    }));
                _service.StartAsync();
                Log.Information($"TcpServer启动成功，监听端口：{serverPort}");
                Task.Run(async delegate
                {
                    //await Task.Delay(1000 * 20);
                    SendHeartBeat();
                });
            }
            catch (Exception ex)
            {
                //throw new InvalidOperationException($"TcpServer启动异常：{ex.Message}");
                Log.Information($"TcpServer启动异常：{ex.Message}");
            }
        }
        public byte DealMessage(byte[] bytes)
        {
            byte XOR = 0;
            try
            {
                byte[] datalen = new byte[bytes.Length - 8];
                Array.Copy(bytes,4,datalen,0, bytes.Length - 8);
                string asciiStr = Encoding.ASCII.GetString(datalen);

                byte[] resultBytes = new byte[asciiStr.Length / 2];
                for (int i = 0; i < asciiStr.Length / 2; i++)
                {
                    int startIndex = i * 2;
                    int length = Math.Min(2, asciiStr.Length - startIndex);
                    string hexPair = asciiStr.Substring(startIndex, length);
                    resultBytes[i] = Convert.ToByte(hexPair, 16);
                }

                XOR = CalculateVerify(resultBytes, resultBytes.Length);
                string sss = XOR.ToString("X2");
                return XOR;
            }
            catch (Exception ex)
            {
                return XOR;
            }
        }
        public byte CalculateVerify(byte[] pMessage, int iLength)
        {
            UInt16 i;
            byte iVerify = 0;

            iVerify = pMessage[0];
            for (i = 1; i < iLength; i++)
            {
                iVerify = (byte)(iVerify ^ pMessage[i]);
            }
            return iVerify;
        }
        public struct Heart
        {
            public Head head;
            public Tail tail;
        }
        public struct Head
        {
            public byte start;                                        //起始
            public byte[] addr;                                       //软件地址
            public byte mstaseq;                                      //主站地址与命令序号
            public byte control;                                      //控制码
            public byte[] length;                                     //数据长度
        }
        public struct Tail
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public byte[] verifica;                                   //校验码
            public byte end;                                        //结束码
        }
        /// <summary>
        /// 向所有客户端发送心跳
        /// </summary>
        public void SendHeartBeat()
        {
            byte[] Heartbuf = new byte[10];
            byte[] u16byte = new byte[2];
            SoftMessagePack pMessagePackInfo = new SoftMessagePack();
            pMessagePackInfo.iStationId = 1;
            pMessagePackInfo.iMsta = 0XF0 + 1;
            pMessagePackInfo.iLen = 0;
            pMessagePackInfo.iMessageType = (byte)MessageType.HeartPack_Type;

            while (true)
            {
                try
                {
                    SendMessage(pMessagePackInfo);
                }
                catch (Exception ex)
                {
                    Log.Information($"SendHeartBeat异常：{ex.Message}");

                }
                Thread.Sleep(1000 * 5 * 1);
            }
        }

        public async void SendMessage(SoftMessagePack pMessagePack)
        {

            UInt16 iPos = 0;
            byte[] u16byte = new byte[2];
            try
            {
                byte[] SendBuffer = new byte[pMessagePack.iLen + 10];
                SendBuffer[iPos] = pMessagePack.iSys;
                iPos += 1;

                u16byte = BitConverter.GetBytes(pMessagePack.iStationId);  //站号
                                                                           //u16byte = Swap16Bytes(u16byte);  //协议里为大端在前
                Array.Copy(u16byte, 0, SendBuffer, iPos, 2);
                iPos += 2;

                SendBuffer[iPos] = pMessagePack.iMsta;    //主站地址   
                iPos += 1;

                SendBuffer[iPos] = pMessagePack.iMessageType;          //帧类型   
                iPos += 1;

                u16byte = BitConverter.GetBytes(pMessagePack.iLen);  //长度
                                                                     //u16byte = Swap16Bytes(u16byte);  //协议里为大端在前
                Array.Copy(u16byte, 0, SendBuffer, iPos, 2);
                iPos += 2;

                if (pMessagePack.iLen > 0)
                {
                    Array.Copy(pMessagePack.pMessage, 0, SendBuffer, iPos, pMessagePack.iLen);   //数据域
                    iPos += (ushort)(pMessagePack.iLen);
                }

                u16byte = _stringChange.CalculateVerifytobyte(SendBuffer, pMessagePack.iLen + 7);   //校验码

                Array.Copy(u16byte, 0, SendBuffer, iPos, 2);
                iPos += 2;

                SendBuffer[iPos] = pMessagePack.iEndChar;   //结束符1
                iPos += 1;

                ReadOnlyMemory<byte> readOnlyMemory = new ReadOnlyMemory<byte>(SendBuffer);
                foreach (var item in _service.Clients)
                {
                    #region Tcp服务器按目标Id先查找再回应
                    if (_service.Clients.TryGetClient(item.Id, out var tcpSessionClient))
                    {
                        await tcpSessionClient.SendAsync(readOnlyMemory);
                    }
                    #endregion
                    Log.Information($"{pMessagePack.iStationId}发送原始报文{_stringChange.bytesToHexStr(SendBuffer, SendBuffer.Length)}");
                }
            }
            catch (Exception ex)
            {
                Log.Information($"SendMessage异常：{ex.Message}");

            }
        }
            
    }
}