using Microsoft.Extensions.Logging;
using SlnMesnac.Config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;

namespace SlnMesnac.TouchSocket
{
    public class TcpServer
    {
        private DebugConfig config = DebugConfig.Instance;
        private ILogger<TcpServer> _logger;
        private readonly TcpService _service;
        #region 委托事件
        /// <summary>
        /// 刷新扫码器状态
        /// </summary>
        /// <param name="materialCodeStr"></param>
        /// <param name="ip"></param>
        public delegate void RefreshState(string ip, bool flag);
        public static event RefreshState RefreshStateEvent;

        //NoRead事件通知
        public delegate void MessageNoRead();
        public static event MessageNoRead MessageNoReadEvent;

        //扫码事件
        public delegate void RefreshMaterialCodeStr(string materialCodeStr, string ip);
        public static event RefreshMaterialCodeStr RefreshMaterialCodeStrEvent;

        //相机拍照识别结果
        public delegate void CameraResult(string result);
        public static event CameraResult CameraResultEvent;


        //光电信号推送
        public delegate void SerialSignalPush(string ip, int flag);
        public static event SerialSignalPush SerialSignalPushEvent;

        #endregion

        public TcpServer(ILogger<TcpServer> logger,TcpService tcpService)
        {
            _logger = logger;
            _service = tcpService;
        }

        public void Init(int serverPort)
        {
            try
            {
                Console.WriteLine("启动Socket服务");
                _service.Connecting = (client, e) => {  
                    _logger.LogInformation($"客户端{client.IP}正在接入服务");
                    return EasyTask.CompletedTask;
                };
                _service.Connected = (client, e) => {   
                    _logger.LogInformation($"客户端{client.IP}接入服务成功");
                    RefreshStateEvent?.Invoke(client.IP, true);
                    return EasyTask.CompletedTask;
                };
                _service.Disconnected = (client, e) => { 
                    _logger.LogInformation($"客户端{client.IP}断开连接");
                    RefreshStateEvent?.Invoke(client.IP, false);
                    return EasyTask.CompletedTask;
                };
                _service.Received = (client, e) =>
                {
                    try
                    {
                      
                        // 串口模块光电信号
                        if (client.IP == config.SerialIP)
                        {
                            int result = ChangeSerialSignal(e.ByteBlock.Buffer,e.ByteBlock.Len);
                            if(result == -1)
                            {
                                client.Logger.Info($"{client.IP}:{client.Port}》接收到光电信息异常");
                            }
                            else
                            {
                                string message = result == 1 ? "触发" : "释放";
                                client.Logger.Info($"{client.IP}:{client.Port}》接收到光电信息:{message}");
                                SerialSignalPushEvent?.Invoke(client.IP, result);
                                
                            }
                            
                           
                        }
                        else  //扫码器及相机
                        {
                            //从客户端收到信息
                            var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意：数据长度是byteBlock.Len

                            //心跳包
                            if (mes == "heartbeat")
                            {
                                //扫码器心跳连接
                                client.Logger.Info($"心跳{client.IP}:{client.Port}》接收到心跳信息：{mes}");
                                RefreshStateEvent?.Invoke(client.IP, true);
                            }
                            else if (mes == "NoRead")
                            {
                                client.Logger.Info($"客户端{client.IP}:{client.Port}》NoRead事件{mes}");

                                MessageNoReadEvent?.Invoke();
                            }
                            else
                            {
                                string code = mes.Trim().TrimEnd('\0');
                                client.Logger.Info($"客户端{client.IP}:{client.Port}》接收到信息：{mes}");
                                // 区分相机扫码器数据
                                if (client.IP == config.ScannerIP)
                                {
                                    if (code.Contains("heart"))
                                    {
                                        return Task.CompletedTask;
                                    }
                                    RefreshMaterialCodeStrEvent?.Invoke(code, client.IP);
                                }
                                else if (client.IP == config.CameraIP)
                                {
                                    // 相机返回数据
                                    CameraResultEvent?.Invoke(code);
                                }


                            }
                        }

                      
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError($"socket接收数据异常:{ex.Message}");
                    }
                    return EasyTask.CompletedTask;
                };

                _service.Setup(new TouchSocketConfig()//载入配置     
                    .SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })
                    .ConfigureContainer(a =>//容器的配置顺序应该在最前面
                    {
                        a.AddConsoleLogger();
                    })
                    .ConfigurePlugins(a =>
                    {
                        //自定义插件
                    }));
                _service.Start();
                _logger.LogInformation($"TcpServer启动成功，监听端口：{serverPort}");
            }
            catch (Exception ex)
            {
                //throw new InvalidOperationException($"TcpServer启动异常：{ex.Message}");
                _logger.LogError($"TcpServer启动异常：{ex.Message}");
            }

        }

        /// <summary>
        /// 向所有客户端发送心跳
        /// </summary>
        //public void SendHeartBeat()
        //{
        //    var clients = _service.SocketClients.GetClients();
        //    foreach (var item in clients)
        //    {
        //        _service.Send(item.Id, "heartbeat");
        //    }
        //}


        /// <summary>
        /// 向指定相机发送指令
        /// </summary>
        public void SendCommand(string ip, string command)
        {
            ISocketClient client = _service.SocketClients.GetClients().FirstOrDefault(x => x.IP ==ip);
            if (client != null)
            {
                _service.Send(client.Id, command);
            }        
        }


        /// <summary>
        /// 转换光电信号
        /// 释放 01 03 02 01 00 B9 D4 
        /// 触发 01 03 02 01 FF F9 94 
        /// </summary>
        /// <returns></returns>
        public int ChangeSerialSignal(byte[] data,int len)
        {
            // 将数据转换为十六进制字符串
            string hexString = BitConverter.ToString(data, 0, len).Replace("-", " ");

            // 打印光电信号
            Console.WriteLine($"光电信号: {hexString}");


            try
            {
                if (data == null || len < 0)
                {
                    return -1;
                }
                len = Math.Min(len, data.Length);
                byte[] CheckByte = new byte[len];
                Array.Copy(data, 0, CheckByte, 0, len);

                byte[] release = new byte[] { (byte)0x01, (byte)0x03, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0xB9, (byte)0xD4 };
                byte[] trigger = new byte[] { (byte)0x01, (byte)0x03, (byte)0x02, (byte)0x01, (byte)0xFF, (byte)0xF9, (byte)0x94 };

                if (CheckByte.Length == release.Length && CheckByte.SequenceEqual(release))
                {

                    return 0;
                }
                else if (CheckByte.Length == trigger.Length && CheckByte.SequenceEqual(trigger))
                {

                    return 1;
                }

                // 异常
                return -1;
            }catch(Exception ex)
            {
                return -1;
            }
        }

    }
}
