using Ems.CollectService.Analysis;
using Ems.CollectService.Common;
using Ems.CollectService.Entity;
using Ems.CollectService.Redis;
using Ems.CollectService.SqlSugarCore;
using NetTaste;
using NLog;
using SqlSugar;
using StackExchange.Redis;
using System;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;

namespace Ems.CollectService.TouchSocket
{
    public sealed class TcpServer
    {
        private static readonly Lazy<TcpServer> lazy = new Lazy<TcpServer>(() => new TcpServer());

        private Logger logger = LogManager.GetCurrentClassLogger();

        private TcpService service = new TcpService();

        private StringChange stringChange = StringChange.Instance;

        private BufferAnalysis bufferAnalysis = BufferAnalysis.Instance;

        private MsgUtil msgUtil = MsgUtil.Instance;

        private JsonChange jsonChange = JsonChange.Instance;

        //private SqlSugarClient baseService = SqlGenerator.GetMySqlInstance();

        //private ConnectionMultiplexer conn = RedisHelper.RedisConn;
        public static TcpServer Instance
        {
            get
            {
                return lazy.Value;
            }
        }

        private TcpServer() { }

        public void Init(int serverPort)
        {
            try
            {
                service.Connecting = (client, e) => {   //有客户端正在连接
                    logger.Info($"客户端{client.IP}正在接入服务");
                };
                service.Connected = (client, e) => {    //有客户端成功连接
                    logger.Trace($"客户端{client.IP}接入服务成功,Id:{client.ID}");
                };
                service.Disconnected = (client, e) => { //有客户端断开连接
                    logger.Trace($"客户端{client.IP}断开连接,Id:{client.ID}");
                    if (client.ID.Length >= 4)
                    {
                        string clientId = string.Format("E{0}", client.ID.ToString().Substring(2, client.ID.ToString().Length - 2));
                        bufferAnalysis.UpdateCollectDeviceOnLineState(clientId, 0);
                    }
                };
                service.Received = (client, byteBlock, requestInfo) =>
                {
                    if (requestInfo is MyFixedHeaderRequestInfo myRequestInfo)
                    {
                        string body = Encoding.UTF8.GetString(myRequestInfo.Body, 0, myRequestInfo.Body.Length);

                        bufferMemory(client, myRequestInfo,service);
                    }
                };

                service.Setup(new TouchSocketConfig()//载入配置     
                    .SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })//同时监听两个地址
                    .SetDataHandlingAdapter(() => { return new MyFixedHeaderCustomDataHandlingAdapter(); })//配置适配器
                    .ConfigureContainer(a =>//容器的配置顺序应该在最前面
                    {
                        a.AddConsoleLogger();//添加一个控制台日志注入(注意:在maui中控制台日志不可用)
                    })
                    .ConfigurePlugins(a =>
                    {
                        //a.Add<CheckClearPlugin>().SetDuration(new TimeSpan(0, 0, 0, 5, 0));

                    }))
                    .Start();//启动
                logger.Info($"采集服务启动成功,监听端口:{serverPort}");
            }
            catch(Exception ex)
            {
                logger.Error($"采集服务启动异常:{ex}");
                throw new Exception(ex.Message);
            }

        }

        /// <summary>
        /// 缓存器
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="requestInfo"></param>
        private void bufferMemory(SocketClient client, MyFixedHeaderRequestInfo requestInfo,TcpService tcpService)
        {
            try
            {
                string header = stringChange.bytesToHexStr(requestInfo.Header, requestInfo.Header.Length);
                string body = stringChange.bytesToHexStr(requestInfo.Body, requestInfo.BodyLength);

                byte[] buffer = new byte[requestInfo.Header.Length + requestInfo.Body.Length];
                Array.Copy(requestInfo.Header, 0, buffer, 0, requestInfo.Header.Length);
                Array.Copy(requestInfo.Body, 0, buffer, requestInfo.Header.Length, requestInfo.Body.Length);

                //var db = conn.GetDatabase();
                switch (requestInfo.Header[7])
                {
                    case 0x21:
                        //登录指令 =>回复登录指令、下发校时指令
                        //db.StringSet("LoginMessage:" + clientId, body, TimeSpan.FromMinutes(10));
                        logger.Info($"{client.ID}登录指令,Header:{header};Body:{body}");
                        bufferAnalysis.LoginMessageHandling(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length,tcpService);
                        break;
                    case 0X24:
                        //心跳指令
                        //db.StringSet("HeartMessage:" + clientId, body, TimeSpan.FromMinutes(10));
                        logger.Info($"{client.ID}心跳指令,Header:{header};Body:{body}");
                        bufferAnalysis.HeartMessageHandlingAsync(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length);
                        break;
                    case 0X08:
                        //请求校时指令
                        logger.Info($"{client.ID}请求校时指令,Header:{header};Body:{body}");
                        bufferAnalysis.CheckTimeHandlingAsync(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length);
                        break;
                    case 131:
                        //电表数据
                        //db.StringSet("DnbMessage:" + clientId, body, TimeSpan.FromMinutes(10));
                        logger.Info($"{client.ID}电表数据,Header:{header};Body:{body}");
                        bufferAnalysis.EDataMessageHandlingAsync(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 1);
                        break;
                    case 132:
                        //水、蒸汽、压缩空气表数据(流量类型)
                        //db.StringSet("FlowMessage:" + clientId, body, TimeSpan.FromMinutes(10));
                        logger.Info($"{client.ID}水表数据,Header:{header};Body:{body}");
                        bufferAnalysis.SDataMessageHandling(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 1);
                        break;

                    case 147:
                        //电表点抄
                        //db.StringSet("DnbMessage:" + clientId, body, TimeSpan.FromMinutes(10));
                        logger.Info($"{client.ID}电表点抄,Header:{header};Body:{body}");
                        bufferAnalysis.EDataMessageHandlingAsync(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 2);
                        break;
                    case 148:
                        //水表点抄
                        //db.StringSet("FlowMessage:" + clientId, body, TimeSpan.FromMinutes(10));
                        logger.Info($"{client.ID}水表点抄,Header:{header};Body:{body}");
                        bufferAnalysis.SDataMessageHandling(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 2);
                        break;
                    default:
                        logger.Info($"{client.ID}指令未匹配到对应类型;");
                        break;
                }
            }
            catch(Exception ex)
            {
                logger.Error("缓存器异常", ex);
            }
        }

        /// <summary>
		/// 点抄指令下发
		/// </summary>
		public void ReadMeterTask(bool isFlag = false)
        {
            if (isFlag == false)
            {
                logger.Info($"未启用点抄仪表功能");
                return;
            }
            try
            {
                var t = Task.Run(async delegate
                {
                    while (true)
                    {
                        //SysConfig sysConfig = baseService.Queryable<SysConfig>().InSingle(14);
                        SysConfig sysConfig = SqlSugarHelper.Db.Queryable<SysConfig>().InSingle(14);
                        if (sysConfig != null)
                        {
                            if (!string.IsNullOrEmpty(sysConfig.ConfigValue))
                            {
                                logger.Warn($"通过参数配置获取到点抄表号:{sysConfig.ConfigValue}");


                                string[] clientIds = sysConfig.ConfigValue.Split('+');

                                foreach (string item in clientIds)
                                {
                                    string clientId = FormatCollectDeviceId(item.Substring(0, 5));
                                    SocketClient[] socketClients = service.GetClients();
                                    
                                    foreach (SocketClient socketClient in socketClients)
                                    {
                                        logger.Warn($"客户端信息打印:{socketClient.ID};{socketClient.IP}");

                                        byte[] buffer = new byte[14];
                                        byte[] collectBuffer = msgUtil.HexStrTorbytes(clientId.Substring(2, 4));

                                        string monitorId = Convert.ToString(msgUtil.ParseToInt(item.Substring(6, 2)), 16).PadLeft(2, '0');
                                        monitorId += Convert.ToString(msgUtil.ParseToInt(item.Substring(8, 2)), 16).PadLeft(2, '0');

                                        byte[] monitorBuffer = msgUtil.HexToString(monitorId);
                                        
                                        Array.Copy(new byte[] { 0x68, 0x45 }, 0, buffer, 0, 2);
                                        Array.Copy(collectBuffer, 0, buffer, 2, collectBuffer.Length);
                                        Array.Copy(new byte[] { 0x00, 0xBF, 0x68, 0x06, 0x00, 0x02 }, 0, buffer, 4, 6);
                                        Array.Copy(monitorBuffer, 0, buffer, 10, monitorBuffer.Length);

                                        /*buffer[10] = Encoding.UTF8.GetBytes(Convert.ToString(msgUtil.ParseToInt(sysConfig.ConfigValue.Substring(6, 2)), 16))[0];
                                        buffer[11] = 0x00;*/

                                        byte csCheck = msgUtil.Check_CS(buffer);
                                        buffer[12] = csCheck;
                                        buffer[13] = 0x16;

                                        socketClient.Send(buffer);
                                        logger.Warn($"向客户端:{socketClient.ID};发送点抄指令:{msgUtil.bytesToHexStr(buffer, (int)buffer.Length)}");
                                    }

                                    await Task.Delay(100 * 2);
                                }


                                sysConfig.ConfigValue = string.Empty;

                                int result = SqlSugarHelper.Db.Updateable<SysConfig>().SetColumns(it => new SysConfig() { ConfigValue = string.Empty, UpdateTime = DateTime.Now }).Where(it => it.ConfigId == 14).ExecuteCommand();

                            }
                        }
                        else
                        {
                            logger.Warn("参数配置信息获取为空");
                        }

                        await Task.Delay(1000 * 2);
                    }
                });
            }
            catch (Exception ex)
            {
                logger.Error($"点抄数据异常:{ex.Message}");
            }
        }

        /// <summary>
		/// 集中器编号格式化=>ClientID
		/// </summary>
		/// <param name="monitorId"></param>
		/// <returns></returns>
		private string FormatCollectDeviceId(string deviceId)
        {
            byte sensorid1 = Convert.ToByte(deviceId.Substring(1, 2));
            byte sensorid2 = Convert.ToByte(deviceId.Substring(3, 2));
            byte[] flag = Encoding.Default.GetBytes(deviceId.Substring(0, 1));
            string collectDeviceId = Convert.ToInt32(flag[0].ToString("x")) + deviceId.Substring(1);
            return collectDeviceId;
        }
    }
}