using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Common;
using Commonlib;
using LogCap.Entity;
using MathNet.Numerics.Distributions;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using NLog;
using RCUHost.Implement;
using RCUHost.Protocols;
using RestSharp;

namespace LogCap.Common
{
    public class DealWithData
    {
        private static Logger _logger = LogManager.GetCurrentClassLogger();
        public static void HandleData(List<byte> data, string source_ip, ushort source_port, string dest_ip, ushort dest_port)
        {

            try
            {

                string fg = Tools.ByteToString(data.ToArray());
                Program.CurrentTime = DateTime.Now;
                List<byte> Header = data.Take(2).ToList();
                List<byte> Len = data.Skip(2).Take(2).ToList();

                int Len_int = BitConverter.ToInt16(Len.ToArray(), 0);

                //系统 ID 的四个字节。固定“T3SA”
                List<byte> ID = data.Skip(4).Take(4).ToList();

                //命令字
                List<byte> CMD = data.Skip(8).Take(1).ToList();

                //Frame
                List<byte> Frame = data.Skip(9).Take(2).ToList();


                //Project_Code
                List<byte> Project_Code = data.Skip(11).Take(2).ToList();

                List<byte> IP3 = data.Skip(13).Take(1).ToList();
                List<byte> IP4 = data.Skip(14).Take(1).ToList();

                List<byte> MsgData = data.Skip(15).Take(Len_int - 15 - 2).ToList();
                List<byte> CRC_byte = data.TakeLast(2).ToList();

                if (source_ip.Equals("106.32.130.149")&&source_port==3386)
                {
                    _logger.Error("data:"+Tools.ByteToString(data.ToArray()));
                }

                string Key = string.Format("{0}_{1}_{2}", CacheKey.RoomIP_Port_Prefix, source_ip, source_port);
                string Dest_Key = string.Format("{0}_{1}_{2}", CacheKey.RoomIP_Port_Prefix, dest_ip, dest_port);

                //Console.WriteLine("Key is: " + Key);

                byte cmdType_byte = CMD[0];
                BLWCommandType cmdtype = (BLWCommandType)cmdType_byte;
                string CommandType = cmdtype.ToString();

                string? iii = ReadConfig.Instance.monitor_server_ip;
                int ppp = ReadConfig.Instance.monitor_server_port;


                var QQQSSS = Program.Cache.Get<List<MonitorEndPoint>>(CacheKey.MonitorEndPointList);
                if (QQQSSS?.Count > 0)
                {

                    string S_R_Type = "";
                    if (source_port == ppp && source_ip.Equals(iii))
                    {
                        S_R_Type = ConstKey.Send_TX;
                    }
                    else
                    {
                        S_R_Type = ConstKey.Receive_RX;
                    }
                    foreach (var item in QQQSSS)
                    {
                        if (item.Port == 0 && item.IPAddress.Equals(source_ip))
                        {
                            EndPoint_Monitor(data, source_ip, source_port, CommandType, S_R_Type);
                        }
                        else
                        {
                            if (item.Port == source_port && item.IPAddress.Equals(source_ip))
                            {
                                EndPoint_Monitor(data, source_ip, source_port, CommandType, S_R_Type);
                            }
                        }
                    }
                }

                //主机注册
                if (cmdType_byte == 0x01)
                {


                    //00 00 00 00  服务器 IP 地址
                    //FF FF FC 00 子网掩码
                    //C0 A8  64 01 网关
                    //0D 0D 端口
                    //34 D0 B8 11 38 89--MAC

                    List<byte> IP = MsgData.Take(4).ToList();
                    List<byte> MaskNet = MsgData.Skip(4).Take(4).ToList();
                    List<byte> GetWay = MsgData.Skip(8).Take(4).ToList();
                    List<byte> Port = MsgData.Skip(12).Take(2).ToList();
                    List<byte> MAC_byte = MsgData.Skip(14).Take(6).ToList();

                    string MACstring = Tools.ByteToString(MAC_byte.ToArray());
                    MACstring = MACstring.Trim().Replace(" ", "-");


                    if (Frame.All(A => A == 0xFF))
                    {
                        CommandType = "服务器注册命令";
                    }


                    if (source_port == ppp && source_ip.Equals(iii))
                    {
                        ReallyDealWith(true, data, dest_ip, dest_port, CommandType, ConstKey.Send_TX);
                    }
                    else
                    {
                        ReallyDealWith(true, data, source_ip, source_port, CommandType);
                    }
                }
                //心跳包，其实会维持 连接
                else if (cmdType_byte == 0x02)
                {

                    //心跳包
                    //心跳包 里面有这个 MAC地址
                    //AA 55 17 00 54 33 53 41
                    //02
                    //F9 FF
                    //A4 06
                    //2C 69 --这个是IP
                    //34 D0 B8 11 2C 69
                    //91 F5
                    //BLWCommandType cmdtype = (BLWCommandType)cmdType_byte;

                    //心跳包可能大于17个
                    //有一些项目的 心跳包是 这样的
                    // aa 55 17 00 54 33 53 41 02 26 ae e9 03 46 b6 34 d0 b8 11 46 b6 29 7e
                    if (source_port == ppp && source_ip.Equals(iii))
                    {
                        ReallyDealWith(true, data, dest_ip, dest_port, CommandType, ConstKey.Send_TX);
                    }
                    else
                    {
                        ReallyDealWith(true, data, source_ip, source_port, CommandType);
                    }
                }
                else
                {

                    //有时候经常上报这样的数据：
                    //AA 55 11 00 54 33 53 41 0E FF FF BF 06 0A C8       E7 72
                    //AA 55 11 00 54 33 53 41 0E FF FF BF 06 0A C6       66 B6 
                    //设备状态上报
                    if (cmdType_byte == 0x0E)
                    {
                        if (MsgData != null && MsgData.Count > 8)
                        {
                            //设备的数量
                            byte[] couont = MsgData.Skip(7).Take(1).ToArray();
                            if (couont.Length > 0)
                            {
                                int Count = couont[0];

                                var MMN = MsgData.Skip(8);
                                for (int j = 0; j < Count; j++)
                                {
                                    var DeviceData = MMN.Skip(j * 5).Take(5).ToArray();
                                    if (DeviceData.Length >= 5 && DeviceData[0] == 0x0A)
                                    {
                                        byte n1 = DeviceData[0];
                                        byte n2 = DeviceData[1];

                                        byte[] vvv = new byte[] { DeviceData[4] };

                                        BitArray bitArray = new BitArray(vvv);

                                        //卡身份
                                        var qqq1 = bitArray.Cast<bool>().Take(1).ToArray();

                                        var qqq2 = bitArray.Cast<bool>().Skip(1).Take(3).ToArray();

                                        var qqq3 = qqq2.ToArray().Prepend(false).ToArray();
                                        //节能状态
                                        if (qqq3.Length >= 4)
                                        {
                                            byte hhhg1 = Tools.CombineBitsToByte(qqq3[3], qqq3[2], qqq3[1], qqq3[0]);
                                        }
                                    }
                                }
                            }
                        }

                    }
                    if (source_port == ppp && source_ip.Equals(iii))
                    {
                        ReallyDealWith(false, data, dest_ip, dest_port, CommandType, ConstKey.Send_TX);
                    }
                    else
                    {
                        ReallyDealWith(false, data, source_ip, source_port, CommandType);
                    }
                }

            }
            catch (Exception ex)
            {
                _logger.Error(ex.Message);
                _logger.Error(ex.StackTrace);
                Console.WriteLine(ex.Message + " \r\n" + ex.StackTrace);
            }
        }

        /// <summary>
        /// IP 和端口 端结点监控
        /// </summary>
        /// <param name="isRegister"></param>
        /// <param name="data"></param>
        /// <param name="source_ip"></param>
        /// <param name="source_port"></param>
        /// <param name="cmdtype"></param>
        /// <param name="Send_Or_Receive"></param>
        private static void EndPoint_Monitor(List<byte> data, string source_ip, ushort source_port, string cmdtype, string Send_Or_Receive = ConstKey.Receive_RX)
        {
            try
            {
                if (data == null || data.Count < 13)
                {
                    return;
                }
                ////系统 ID 的四个字节。固定“T3SA”
                //List<byte> ID = data.Skip(4).Take(4).ToList();

                ////命令字
                //List<byte> CMD = data.Skip(8).Take(1).ToList();

                ////Frame
                //List<byte> Frame = data.Skip(9).Take(2).ToList();


                //Project_Code
                List<byte> Project_Code = data.Skip(11).Take(2).ToList();
                if (Project_Code.Count >= 2)
                {
                    ushort hotel_code_o = BitConverter.ToUInt16(Project_Code.ToArray(), 0);

                    ////MAC
                    //List<byte> IP3 = data.Skip(13).Take(1).ToList();
                    //List<byte> IP4 = data.Skip(14).Take(1).ToList();

                    long hotel_code = hotel_code_o;
                    string hostnumber = "";
                    string hexdata = Tools.ByteToString(data.ToArray());
                    HttpSend.SendLog_2(cmdtype, hotel_code, 0, "", hostnumber, source_ip, source_port, "", 0, "", Send_Or_Receive, hexdata);
                }
            }
            catch (Exception)
            {

                throw;
            }
        }

        public static void ReallyDealWith(bool isRegister, List<byte> data, string source_ip, ushort source_port, string cmdtype, string Send_Or_Receive = ConstKey.Receive_RX)
        {
            try
            {
                if (data == null || data.Count == 0)
                {
                    return;
                }
                ReceiverContext context = new ReceiverContext(data.ToArray());
                context.SystemHeader = DecodeSystemHeader(context.Data);

                if (!context.SystemHeader.HasValue)
                {
                    return;
                }

                string Ghostnumber = context.SystemHeader.Value.HostNumber.ToString() ?? "";
                if (string.IsNullOrEmpty(Ghostnumber))
                {
                    return;
                }
                long HHH = 0;
                try
                {
                    HHH = context.SystemHeader.Value.HostNumber.ToHotelCode();
                }
                catch (Exception)
                {
                    var data_error = Tools.ByteToString(data.ToArray());
                    Console.WriteLine("ErrorData" + data_error);
                    return;
                }
                //var MAC = BitConverter.ToString(context.Data.Skip(9).Take(2).ToArray());

                //if (MAC.ToLower().Equals("9CD6"))
                //{
                //    _logger.Info("MAC:" + MAC);
                //    _logger.Info("data:" + Tools.ByteToString(data.ToArray()));
                //}

                var list = Program.Cache.Get<List<Monitor_Host>>(CacheKey.Key);

                if (HHH == 1197)
                {
                    //Console.WriteLine("data:" + Tools.ByteToString(data.ToArray()));
                    //Console.WriteLine(JsonConvert.SerializeObject(list));
                }
                if (list == null)
                {
                    return;
                }
                if (list.Count == 0)
                {
                    return;
                }
                if (isRegister)
                {
                    if (list != null && list.Count > 0)
                    {
                        #region 删除过期的数据
                        try
                        {

                            list.RemoveAll((Item) =>
                            {
                                if (Item != null)
                                {
                                    var ddt = Item.CreateDateTime;
                                    if (!string.IsNullOrEmpty(ddt))
                                    {
                                        DateTime dta = DateTime.Parse(ddt);

                                        DateTime nnn = dta.AddDays(30);
                                        if (DateTime.Now >= nnn)
                                        {
                                            return true;
                                        }
                                    }
                                }
                                return false;
                            });
                        }
                        catch (Exception)
                        {

                        }
                        #endregion
                        foreach (Monitor_Host item in list)
                        {
                            try
                            {
                                if (item == null)
                                {
                                    continue;
                                }
                                string HostNNN = item.Key_HostNumber;
                                if (HostNNN == null)
                                {
                                    continue;
                                }

                                string room_num = item.RoomNumber;
                                string TakeOut_MAC = item.MAC;
                                string hotelcode = item.HotelCode;

                                //如果 要监控的MAC 和 当前上传的MAC相等
                                if (HostNNN.Equals(Ghostnumber))
                                {

                                    if (HHH == 1197)
                                    {
                                        //Console.WriteLine("111111 "+isRegister);
                                        //Console.WriteLine("111111 data:" + Tools.ByteToString(data.ToArray()));
                                    }
                                    //心跳包可以注册
                                    if (isRegister)
                                    {
                                        var llg = Tools.ByteToString(data.ToArray());
                                        string KeyHeartBeat = string.Format("{0}_{1}_{2}", CacheKey.RoomIP_Port_Prefix, source_ip, source_port);
                                        //Console.WriteLine("TakeOut_HostNUMBER: " + HostNNN + " Key: " + KeyHeartBeat + " MAC: " + TakeOut_MAC + " data:" + llg);
                                        Program.Cache.Set<string>(KeyHeartBeat, HostNNN);
                                    }

                                    string Key = string.Format("{0}_{1}", CacheKey.RoomIP_Port_Prefix, HostNNN);
                                    var takeMM = Program.Cache.Get<MonitorRedis>(Key);

                                    if (HHH == 1197)
                                    {
                                        //Console.WriteLine("1197::::"+JsonConvert.SerializeObject(takeMM));
                                    }
                                    //如果房间为空
                                    if (takeMM == null)
                                    {
                                        #region 查询房间信息
                                        //从数据库里面查询得
                                        Dictionary<string, string> dic = new Dictionary<string, string>();
                                        dic.Add("key", "blw_ws@2015");
                                        dic.Add("roomnumber", room_num);
                                        dic.Add("hotelcode", hotelcode);

                                        string sttr = "";
                                        string KKK = "ChaXunData_" + hotelcode + "_" + room_num;
                                        string GGG = Program.Cache.Get<string>(KKK);
                                        if (!string.IsNullOrEmpty(GGG))
                                        {
                                            sttr = GGG;
                                        }
                                        else
                                        {
                                            //SqlConnection con = new SqlConnection("");
                                            //con.Open();

                                            sttr = Send_Http_Request_Params("api/GetHostByMAC_POST", dic);
                                            Program.Cache.Set<string>(KKK, GGG, new MemoryCacheEntryOptions()
                                            {
                                                SlidingExpiration = TimeSpan.FromMinutes(10)
                                            });
                                        }

                                        if (!string.IsNullOrEmpty(sttr))
                                        {

                                            //Console.WriteLine(  "查询的数据："+sttr);
                                            var msghost = JsonConvert.DeserializeObject<HostMsg>(sttr);
                                            var dtrow = msghost.Result.FirstOrDefault();
                                            if (dtrow != null)
                                            {

                                                string? hotelid = dtrow["HotelID"].ToString();
                                                string? hostid = dtrow["ID"].ToString();
                                                string? roomno = dtrow["RoomNumber"].ToString();
                                                string? hostnumber = dtrow["HostNumber"].ToString();
                                                string? LanIP = dtrow["LanIP"] ?? "";
                                                string? LanPort = dtrow["LanPort"].ToString();
                                                string? HotelID = dtrow["HotelID"].ToString();
                                                //string? XiaoDuCUID = dtrow["XiaoDuCUID"].ToString();
                                                //string? TiaoMaoCUID = dtrow["TiaoMaoCUID"].ToString();

                                                string? XiaoDuCUID = "";
                                                string? TiaoMaoCUID = "";
                                                MonitorRedis mm = new MonitorRedis();
                                                long hhh = 0;
                                                long.TryParse(hotelcode, out hhh);

                                                int hid = 0;
                                                int.TryParse(HotelID, out hid);

                                                mm.TiaoMaoCUID = TiaoMaoCUID;
                                                mm.XiaoDuCUID = XiaoDuCUID;
                                                mm.HotelCode = hhh;
                                                mm.HotelID = hid;

                                                mm.HostID = int.Parse(hostid);

                                                mm.RoomNo = roomno;
                                                mm.HostNumber = hostnumber;

                                                mm.WWW_IP = source_ip;
                                                mm.WWW_Port = source_port;

                                                mm.LanIP = LanIP;
                                                mm.LanPort = int.Parse(LanPort);

                                                mm.MAC = TakeOut_MAC;

                                                mm.CommandType = cmdtype.ToString();
                                                mm.SendOrReceive = Send_Or_Receive;

                                                mm.RemoteEndPointIP = source_ip;
                                                mm.RemoteEndPointPort = source_port;
                                                Program.Cache.Set<MonitorRedis>(Key, mm);

                                                string dataHex = Tools.ByteToString(data.ToArray());

                                                HttpSend.SendLog(mm.XiaoDuCUID, mm.TiaoMaoCUID, mm.CommandType, hhh, mm.HostID, mm.RoomNo, mm.HostNumber, source_ip, source_port, mm.LanIP, mm.LanPort, mm.MAC, Send_Or_Receive, dataHex);
                                            }
                                        }
                                        #endregion
                                    }
                                    else
                                    {
                                        if (hotelcode.Equals("1197"))
                                        {
                                            Console.WriteLine("upload data");
                                        }
                                        long hotel_code = takeMM.HotelCode;
                                        int host_id = takeMM.HostID;

                                        string hostnumber = takeMM.HostNumber;
                                        string roomnumber = takeMM.RoomNo;

                                        string lan_ip = takeMM.LanIP;
                                        int lan_port = takeMM.LanPort;

                                        string www_ip = takeMM.WWW_IP;
                                        int www_port = takeMM.WWW_Port;

                                        string mac_take_out = takeMM.MAC;
                                        string dataHex = Tools.ByteToString(data.ToArray());
                                        HttpSend.SendLog(takeMM.XiaoDuCUID, takeMM.TiaoMaoCUID, cmdtype, hotel_code, host_id, roomnumber, hostnumber, www_ip, www_port, lan_ip, lan_port, mac_take_out, Send_Or_Receive, dataHex);
                                    }
                                    break;
                                }
                            }
                            catch (Exception ex)
                            {
                                continue;
                            }
                        }
                    }
                }
                else
                {
                    if (list != null && list.Count > 0)
                    {
                        string KeyHeartBeat = string.Format("{0}_{1}_{2}", CacheKey.RoomIP_Port_Prefix, source_ip, source_port);
                        string Hostnumber_TTT = Program.Cache.Get<string>(KeyHeartBeat);
                        if (!string.IsNullOrEmpty(Hostnumber_TTT))
                        {
                            string Key = string.Format("{0}_{1}", CacheKey.RoomIP_Port_Prefix, Hostnumber_TTT);
                            //Console.WriteLine("KeyHeartBeat is " + KeyHeartBeat);
                            if (!string.IsNullOrEmpty(Key))
                            {
                                //string bbbaaa=Tools.ByteToString(data.ToArray());
                                //Console.WriteLine("111111111111111111: "+Key+" data: "+bbbaaa);
                                var takeMM = Program.Cache.Get<MonitorRedis>(Key);
                                if (takeMM != null)
                                {
                                    //Console.WriteLine("22222222222");
                                    long hotel_code = takeMM.HotelCode;
                                    int host_id = takeMM.HostID;

                                    string hostnumber = takeMM.HostNumber;
                                    string roomnumber = takeMM.RoomNo;

                                    string lan_ip = takeMM.LanIP;
                                    int lan_port = takeMM.LanPort;

                                    string www_ip = takeMM.WWW_IP;
                                    int www_port = takeMM.WWW_Port;

                                    string mac_take_out = takeMM.MAC;
                                    string dataHex = Tools.ByteToString(data.ToArray());
                                    HttpSend.SendLog("", "", cmdtype, hotel_code, host_id, roomnumber, hostnumber, www_ip, www_port, lan_ip, lan_port, mac_take_out, Send_Or_Receive, dataHex);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("出错了" + ex.Message);
                Console.WriteLine("出错了" + ex.StackTrace);
                _logger.Error(ex.Message);
                _logger.Error(ex.StackTrace);
            }
        }
        private static SystemHeader? DecodeSystemHeader(byte[] data)
        {
            return StructConverter.BytesToStruct(data, typeof(SystemHeader)) as SystemHeader?;
        }
        public static string Send_Http_Request_Params(string Url, Dictionary<string, string> Params)
        {
            string BaseUrl = ReadConfig.Instance.CRICS_URL;
            var options = new RestClientOptions(BaseUrl);
            var client = new RestClient(options);

            var request = new RestRequest(Url);

            foreach (var item in Params)
            {
                request.AddParameter(item.Key, item.Value);
            }
            //RoomNumber
            // The cancellation token comes from the caller. You can still make a call without it.
            string? hostlist = client.Post(request).Content;
            return hostlist;
        }
    }

}
