using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Threading;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
//using Ropin.Environmentally.MqttService;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace Ropin.Environmentally.LoRaService
{
    public class TCPServer
    {
        public IConfiguration configuration;
        private readonly IMemoryCache memoryCache;

        public static List<LoRaDevicePoint> _mqttDevicePointList;
        public static ConcurrentDictionary<string, LoRaDevicePoint> _mqttDevicePointDic;
        public static ConcurrentDictionary<string, string> _mqttDevicePointNameMappingDic;

        Timer timer;
        /// <summary>
        /// tcp服务器
        /// </summary>
        private TcpListener listener;
        /// <summary>
        /// 初始化tcp服务器
        /// </summary>
        public TCPServer(IConfiguration configuration, IMemoryCache memoryCache)
        {
            _mqttDevicePointList = new List<LoRaDevicePoint>();
            _mqttDevicePointDic = new ConcurrentDictionary<string, LoRaDevicePoint>();
            _mqttDevicePointNameMappingDic = new ConcurrentDictionary<string, string>();
            //从表读取
            //_mqttDevicePointList.Add(new LoRaDevicePoint { Id = "09d9ce00-8c61-4abb-8a8b-26e2fbf62e66", ChineseName = "工作正常", BoxId = "88888880000002", EnglishName = "a00000-Avg", GroupName = "分组1" });
            //_mqttDevicePointList.Add(new LoRaDevicePoint { Id = "09d9ce00-8c61-4abb-8a8b-26e2fbf62e67", ChineseName = "报警", BoxId = "88888880000002", EnglishName = "a05002-Avg", GroupName = "分组1" });
            //_mqttDevicePointList.Add(new LoRaDevicePoint { Id = "09d9ce00-8c61-4abb-8a8b-26e2fbf62e68", ChineseName = "电源正常", BoxId = "88888880000002", EnglishName = "a25003-Avg", GroupName = "分组1" });
            //_mqttDevicePointList.Add(new LoRaDevicePoint { Id = "09d9ce00-8c61-4abb-8a8b-26e2fbf62e69", ChineseName = "手工报警", BoxId = "88888880000002", EnglishName = "a01014-Avg", GroupName = "分组1" });

            //foreach (var dp in _mqttDevicePointList)
            //{
            //    _mqttDevicePointDic.TryAdd(dp.BoxId + "分组1" + dp.EnglishName, dp);
            //    _mqttDevicePointNameMappingDic.TryAdd(dp.BoxId + "分组1" + dp.ChineseName, dp.BoxId + "分组1" + dp.EnglishName);
            //}

            this.memoryCache = memoryCache;
            this.configuration = configuration;
            this.listener = new TcpListener(IPAddress.Any, Port);
            //timer = new Timer(SendMessage);
            //timer.Change(1000, Interval);

            string stringMessage = @"##1058QN=20231108172341488;ST=32;CN=2051;PW=123456;MN=88888880000002;Flag=4;CP=&&DataTime=20231107145300;a00000-Cou=1924.7205,a00000-Min=32.0193,a00000-Avg=32.0787,a00000-Max=32.1106,a00000-Flag=N;a05002-Cou=0.0033,a05002-Min=1.5700,a05002-Avg=1.5700,a05002-Max=1.5700,a05002-Flag=N;a24087-Cou=0.0141,a24087-Min=6.7000,a24087-Avg=6.7000,a24087-Max=6.7000,a24087-Flag=N;a24088-Cou=0.0108,a24088-Min=5.1300,a24088-Avg=5.1300,a24088-Max=5.1300,a24088-Flag=N;a25002-Cou=0.0000,a25002-Min=0.0000,a25002-Avg=0.0000,a25002-Max=0.0000,a25002-Flag=N;a25003-Cou=0.0009,a25003-Min=0.4200,a25003-Avg=0.4200,a25003-Max=0.4200,a25003-Flag=N;a25005-Cou=0.0004,a25005-Min=0.1900,a25005-Avg=0.1900,a25005-Max=0.1900,a25005-Flag=N;a01011-Cou=0.0195,a01011-Min=9.2200,a01011-Avg=9.2460,a01011-Max=9.2600,a01011-Flag=N;a01012-Cou=0.0496,a01012-Min=23.5200,a01012-Avg=23.5265,a01012-Max=23.5300,a01012-Flag=N;a01013-Cou=-0.0001,a01013-Min=-0.0320,a01013-Avg=-0.0301,a01013-Max=0.0000,a01013-Flag=N;a01014-Cou=0.0017,a01014-Min=0.7400,a01014-Avg=0.7855,a01014-Max=0.8100,a01014-Flag=N&&59C0";
            AnalysisOnLineString(stringMessage);
            //if (!string.IsNullOrWhiteSpace(stringMessage) && stringMessage.StartsWith("##"))
            //{
            //    MqttDeviceData mqttDeviceData = new MqttDeviceData();
            //    string[] fenghaoSplit = stringMessage.Split(";");
            //    for (int i = 0; i < fenghaoSplit.Length; i++)
            //    {
            //        if(fenghaoSplit[i].Contains(","))
            //        {
            //            string[] duhaoSplit = fenghaoSplit[i].Split(",");
            //            for (int j=0;j< duhaoSplit.Length;j++)
            //            {
            //                string[] denghaoSplit = duhaoSplit[j].Split("=");
            //                if (mqttDeviceData.data == null)
            //                    mqttDeviceData.data = new Dictionary<string, string>();
            //                mqttDeviceData.data.TryAdd(denghaoSplit[0], denghaoSplit[1]);
            //            }


            //        }
            //        else
            //        {
            //            string[] denghaoSplit = fenghaoSplit[i].Split("=");
            //            switch (denghaoSplit[0])
            //            {
            //                case "ST":
            //                    mqttDeviceData.ST = denghaoSplit[1];
            //                    break;
            //                case "CN":
            //                    mqttDeviceData.CN = denghaoSplit[1];
            //                    break;
            //                case "PW":
            //                    mqttDeviceData.PW = denghaoSplit[1];
            //                    break;
            //                case "MN":
            //                    mqttDeviceData.MN = denghaoSplit[1];
            //                    mqttDeviceData.boxid = denghaoSplit[1];
            //                    break;
            //                case "Flag":
            //                    mqttDeviceData.Flag = denghaoSplit[1];
            //                    break;
            //                case "CP":
            //                    mqttDeviceData.CP = denghaoSplit[1];
            //                    break;
            //                case "DataTime":
            //                    mqttDeviceData.DataTime = denghaoSplit[1];
            //                    break;
            //                default:
            //                    break;
            //            }
            //        }


            //    }
            //    foreach (var dp in mqttDeviceData.data)
            //    {
            //        if(!_mqttDevicePointDic.ContainsKey(mqttDeviceData.boxid + "分组1" + dp.Key))
            //            _mqttDevicePointDic.TryAdd(mqttDeviceData.boxid + "分组1" + dp.Key, new LoRaDevicePoint { Id = Guid.NewGuid().ToString(), ChineseName = dp.Key, BoxId = mqttDeviceData.boxid, EnglishName = dp.Key, GroupName = "分组1" });
            //        if (!_mqttDevicePointNameMappingDic.ContainsKey(mqttDeviceData.boxid + "分组1" + dp.Key))
            //            _mqttDevicePointNameMappingDic.TryAdd(mqttDeviceData.boxid + "分组1" + dp.Key, mqttDeviceData.boxid + "分组1" + dp.Key);
            //    }

            //    if (mqttDeviceData != null && mqttDeviceData.data.Count > 0)
            //    {
            //        foreach (var key in mqttDeviceData.data.Keys)
            //        {
            //            LoRaDevicePoint mqttDevicePoint = _mqttDevicePointDic[mqttDeviceData.boxid + "分组1" + key];
            //            mqttDevicePoint.BoxStatus = "1";
            //            mqttDevicePoint.DataType = "3";
            //            mqttDevicePoint.UpLoadTime = DateTime.Now;
            //            mqttDevicePoint.Value = mqttDeviceData.data[key];
            //            _mqttDevicePointDic[mqttDeviceData.boxid + "分组1" + key] = mqttDevicePoint;
            //        }
            //    }

            //}
        }
        public class MqttDeviceData
        {
            public Dictionary<string, string> data { set; get; }
            public string boxid { set; get; }


            public string QN { set; get; }
            public string ST { set; get; }
            public string CN { set; get; }
            public string PW { set; get; }
            public string MN { set; get; }
            public string Flag { set; get; }
            public string CP { set; get; }
            public string DataTime { set; get; }

            //public string DataTime { set; get; }

        }
        private void AnalysisOnLineString(string stringMessage)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(stringMessage) && stringMessage.StartsWith("##"))
                {
                    MqttDeviceData mqttDeviceData = new MqttDeviceData();
                    string[] fenghaoSplit = stringMessage.Split(";");
                    for (int i = 0; i < fenghaoSplit.Length; i++)
                    {
                        if (fenghaoSplit[i].Contains(","))
                        {
                            string[] duhaoSplit = fenghaoSplit[i].Split(",");
                            for (int j = 0; j < duhaoSplit.Length; j++)
                            {
                                string[] denghaoSplit = duhaoSplit[j].Split("=");
                                if (mqttDeviceData.data == null)
                                    mqttDeviceData.data = new Dictionary<string, string>();
                                mqttDeviceData.data.TryAdd(denghaoSplit[0], denghaoSplit[1]);
                            }


                        }
                        else
                        {
                            string[] denghaoSplit = fenghaoSplit[i].Split("=");
                            switch (denghaoSplit[0])
                            {
                                case "ST":
                                    mqttDeviceData.ST = denghaoSplit[1];
                                    break;
                                case "CN":
                                    mqttDeviceData.CN = denghaoSplit[1];
                                    break;
                                case "PW":
                                    mqttDeviceData.PW = denghaoSplit[1];
                                    break;
                                case "MN":
                                    mqttDeviceData.MN = denghaoSplit[1];
                                    mqttDeviceData.boxid = denghaoSplit[1];
                                    break;
                                case "Flag":
                                    mqttDeviceData.Flag = denghaoSplit[1];
                                    break;
                                case "CP":
                                    mqttDeviceData.CP = denghaoSplit[1];
                                    break;
                                case "DataTime":
                                    mqttDeviceData.DataTime = denghaoSplit[1];
                                    break;
                                default:
                                    break;
                            }
                        }


                    }
                    foreach (var dp in mqttDeviceData.data)
                    {
                        if (!_mqttDevicePointDic.ContainsKey(mqttDeviceData.boxid + "分组1" + dp.Key))
                            _mqttDevicePointDic.TryAdd(mqttDeviceData.boxid + "分组1" + dp.Key, new LoRaDevicePoint { Id = Guid.NewGuid().ToString(), ChineseName = dp.Key, BoxId = mqttDeviceData.boxid, EnglishName = dp.Key, GroupName = "分组1" });
                        if (!_mqttDevicePointNameMappingDic.ContainsKey(mqttDeviceData.boxid + "分组1" + dp.Key))
                            _mqttDevicePointNameMappingDic.TryAdd(mqttDeviceData.boxid + "分组1" + dp.Key, mqttDeviceData.boxid + "分组1" + dp.Key);
                    }

                    if (mqttDeviceData != null && mqttDeviceData.data.Count > 0)
                    {
                        foreach (var key in mqttDeviceData.data.Keys)
                        {
                            LoRaDevicePoint mqttDevicePoint = _mqttDevicePointDic[mqttDeviceData.boxid + "分组1" + key];
                            mqttDevicePoint.BoxStatus = "1";
                            mqttDevicePoint.DataType = "3";
                            mqttDevicePoint.UpLoadTime = DateTime.Now;
                            mqttDevicePoint.Value = mqttDeviceData.data[key];
                            _mqttDevicePointDic[mqttDeviceData.boxid + "分组1" + key] = mqttDevicePoint;
                        }
                    }

                }
            }
            catch (Exception ex)
            {
                Debug.Write(ex.InnerException);
            }
        }

        /// <summary>
        /// 轮询间隔时间
        /// </summary>
        private int Interval
        {
            get { return configuration.GetValue<int>("TimerInterval"); }
        }

        /// <summary>
        /// 端口号
        /// </summary>
        private int Port
        {
            get { return configuration.GetValue<int>("Port"); }
        }

        /// <summary>
        /// 客户端集合
        /// </summary>
        private List<TcpClient> clients = new List<TcpClient>();

        public List<TcpClient> Clients { get { return clients; } }

        /// <summary>
        /// 开启服务器监听
        /// </summary>
        public void Start()
        {
            listener.Start();
            listener.BeginAcceptTcpClient(new AsyncCallback(Acceptor), listener);
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            listener.Stop();
        }

        private void Acceptor(IAsyncResult o)
        {
            try
            {
                TcpListener listener = o.AsyncState as TcpListener;
                TcpClient client = listener?.EndAcceptTcpClient(o);
                IPEndPoint ipep = client?.Client.RemoteEndPoint as IPEndPoint;
                IPAddress ipa = ipep.Address;
                Console.WriteLine("客户端 : " + ipa.ToString() + " 已连接");
                clients.Add(client);
                listener?.BeginAcceptTcpClient(new AsyncCallback(Acceptor), listener);
                Task.Run(() =>
                {
                    while (client.Connected)
                    {
                        if (client != null)
                        {
                            NetworkStream stream = client.GetStream();
                            byte[] buffer = new byte[1024 * 1024];
                            int i = 0;
                            i = stream.Read(buffer, 0, buffer.Length);
                            byte[] data = buffer.Take(i).ToArray();

                            if (i != 0)
                            {
                                System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
                                String stringMessage = asciiEncoding.GetString(data);
                                //Console.WriteLine(BitConverter.ToString(StringMessage));//将字节数组转换为字符串并输出
                                Console.WriteLine("接受的字符串:" + stringMessage);//将字节数组转换为字符串并输出
                                //var payload = Encoding.UTF8.GetString(arg?.ApplicationMessage?.PayloadSegment.ToArray());

                                AnalysisOnLineString(stringMessage);

                                //验证数据.
                                var validateCode = CRCHelper.Crc16Modbus(data);
                                var validate = StringHelper.ByteToHexString(validateCode).Replace(" ", "") == "0000";
                                var hexMessage = StringHelper.ByteToHexString(data);
                                if (validate)
                                {
                                    //Console.WriteLine($"验证成功,客户端{ipa.ToString()}发来了HEX消息为:" + hexMessage);
                                    var moduleId = StringHelper.ByteToHexString(data.Skip(4).Take(4).ToArray());
                                    //Console.WriteLine($"客户端{ipa.ToString()}模块id:" + moduleId);
                                    var status = StringHelper.ByteToHexString(data.Skip(8).Take(1).ToArray());
                                    //Console.WriteLine($"客户端{ipa.ToString()}状态:" + status);

                                    var dianyaHex = StringHelper.ByteToHexString(data.Skip(20).Take(2).ToArray());
                                    var dianya = Convert.ToInt32(dianyaHex.Replace(" ", ""), 16);
                                    //Console.WriteLine($"客户端{ipa.ToString()}电压:" + dianya + "  HEX:" + dianyaHex);

                                    var dianliuHex = StringHelper.ByteToHexString(data.Skip(22).Take(2).ToArray());
                                    var dianliu = Convert.ToInt32(dianliuHex.Replace(" ", ""), 16);
                                    //Console.WriteLine($"客户端{ipa.ToString()}电流:" + dianliu + "  HEX:" + dianliuHex);
                                    DataModel requestModel;

                                    try
                                    {
                                        requestModel = new DataModel();
                                        requestModel.ModuleId = moduleId;
                                        requestModel.Status = status == "80" || status == "88" || status == "00" ? 0 : 1;
                                        requestModel.devSpots.Add(new DevSpot
                                        {
                                            Name = "电压",
                                            Value = dianya,
                                            DataType = 0
                                        });
                                        requestModel.devSpots.Add(new DevSpot
                                        {
                                            Name = "电流",
                                            Value = dianliu,
                                            DataType = 0
                                        });

                                        var json = JsonConvert.SerializeObject(requestModel);
                                        memoryCache.Set(moduleId, json);
                                    }
                                    catch (Exception ex)
                                    {
                                        Console.WriteLine(ex.Message);
                                    }
                                }
                                else
                                {
                                    Console.WriteLine($"验证失败,客户端{ipa.ToString()}发来了HEX消息为:" + hexMessage);
                                }
                            }
                            else
                            {
                                client.Close();
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取16进制字符串中的命令消息
        /// </summary>
        /// <param name="hexMessage"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private string GetCommand(string hexMessage, byte[] data)
        {
            var msg = hexMessage.Split(' ');
            var length = Convert.ToInt32(msg[1], 16);
            Console.WriteLine("数据长度为:" + length);
            if (length > data.Length)
            {
                return "ERROR : 命令长度大于消息长度.";
            }
            else
            {
                byte[] command = data.Skip(2).Take(length).ToArray();
                var hexMessage1 = string.Empty;
                foreach (var item in command)
                {
                    hexMessage1 += item.ToString("X2") + " ";
                }
                return hexMessage1;
            }
        }

        //public void SendMessage(object state)
        //{
        //    Console.WriteLine("准备发送轮训消息");

        //    foreach (var client in clients.ToArray())
        //    {
        //        if (client.Connected)
        //        {
        //            NetworkStream stream = client.GetStream();
        //            Byte[] data = StringHelper.StringToHexByte("EA 11 01 1F 10 2B 00 01 00 00 00 00 00 00 00 00 00 00 00 82 5E");
        //            // Send the message to the connected TcpServer.
        //            stream.Write(data, 0, data.Length);
        //            Console.WriteLine($"消息发送成功..");
        //        }
        //        else
        //        {
        //            Console.WriteLine($"客户端已经断开连接.");
        //            clients.Remove(client);
        //        }
        //    }
        //}


        //private string Url = "https://www.ropintechjxbooksys.com/DigitalEnvironment/api/TdevWebScadaDevSpot/SaveDevSpotValueByRedis";
        ///// <summary>
        ///// 接口调用
        ///// </summary>
        ///// <param name="url"></param>
        ///// <param name="data"></param>
        ///// <returns></returns>
        //public string PostData(string data)
        //{
        //    string strResult = "";
        //    try
        //    {
        //        var httpContent = new StringContent(data, Encoding.UTF8, "application/json");

        //        //string url = GetConfigUrl(encode);

        //        HttpClient httpClient = new HttpClient();
        //        HttpResponseMessage response = httpClient.PostAsync(Url, httpContent).Result;

        //        if (response.IsSuccessStatusCode)
        //        {
        //            strResult = response.Content.ReadAsStringAsync().Result;
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        Console.WriteLine(ex.Message);
        //    }

        //    return strResult;
        //}
    }
}