using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Common;
using Domain;
using RCUHost.Protocols;
using Dao;
using RestSharp;
using System.Threading.Tasks;
using System.Configuration;
using CommonEntity;

namespace RCUHost.Implement
{
    /// <summary>
    /// 发送命令给rcu，获取寄存器内容：改为读取主机信息命令
    /// </summary>
    public class HostRegisterReceiver : GenericReceiverBase, IHostRegisterReceiver
    {
        private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(HostRegisterReceiver));
        public IHostRepository HostRepository { get; set; }
        public IHostRCURepository HostRCURepository { get; set; }
        public IRoomStatusRepository RoomStatusRepository { get; set; }

        public void Send(Host host)
        {
            var data = CreateHostSecretPacket(host);
            Send(data, host.HostNumber, host.MAC);
        }

        public void Send(string hostnumber, string mac)
        {
            var data = CreateHostSecretPacket();
            Send(data, hostnumber, mac);
        }

        public byte[] CreateHostSecretPacket()
        {
            SystemHeader systemHeader = CreateSystemHeader();
            byte[] registerAddr = new byte[] { 0, 0, 0, 0 };
            int size = StructConverter.SizeOf(systemHeader) + 2 + registerAddr.Length;
            systemHeader.FrameLength = (ushort)size;
            using (MemoryStream stream = new MemoryStream(size))
            {
                using (BinaryWriter writer = new BinaryWriter(stream))
                {
                    writer.Write(StructConverter.StructToBytes(systemHeader));
                    writer.Write(registerAddr);
                    writer.Write(new byte[] { 0, 0 });
                    return stream.ToArray();
                }
            }
        }
        public byte[] CreateHostSecretPacket(Host host)
        {
            SystemHeader systemHeader = CreateSystemHeader();
            byte[] registerAddr = new byte[] { 0, 0, 0, 0 };
            //byte[] registerAddr = new byte[] { 
            //    13,             //需要读取寄存器的个数
            //    0, 0, 0, 0,     //局域網IP
            //    4, 0, 0, 0,     //局域网端口
            //    8, 0, 0, 0,     //子网掩码
            //    12, 0, 0, 0,    //网关
            //    16, 0, 0, 0,    //DNS
            //    24, 0, 0, 0,    //服务器IP
            //    28, 0, 0, 0,    //服务器端口
            //    32, 0, 0, 0,    //授权到期时间
            //    40, 0, 0, 0,    //设置到期时间
            //    48, 0, 0, 0,    //IP类型
            //    60, 0, 0, 0,    //固件版本号
            //    64, 0, 0, 0,    //配置版本号
            //    80, 0, 0, 0     //季节
            //};
            int size = StructConverter.SizeOf(systemHeader) + 2 + registerAddr.Length;
            systemHeader.FrameLength = (ushort)size;
            using (MemoryStream stream = new MemoryStream(size))
            {
                using (BinaryWriter writer = new BinaryWriter(stream))
                {
                    writer.Write(StructConverter.StructToBytes(systemHeader));
                    writer.Write(registerAddr);
                    writer.Write(new byte[] { 0, 0 });
                    return stream.ToArray();
                }
            }
        }

        //public static string Debug_RegeditInfo = ConfigurationManager.AppSettings["debug_registerinfo"];
        public override void Process(ReceiverContext context)
        {
            string msg = context.RemoteEndPoint.Address.ToString() + ":" + context.RemoteEndPoint.Port.ToString() + ":" + Tools.ByteToString(context.Data);
            //logger.Error("收到主机信息数据：" + msg);


            string dataHex = Tools.ByteToString(context.Data);
            string HostNumberOnly = context.SystemHeader.Value.HostNumber.ToString();
            Host host = HostRepository.GetByHostNumber(HostNumberOnly);

            if (host != null)
            {
                try
                {
                    int offset = StructConverter.SizeOf(context.SystemHeader);
                    int length = context.Data.Length - offset - 2;
                    using (MemoryStream stream = new MemoryStream(context.Data, offset, length))
                    {
                        using (BinaryReader reader = new BinaryReader(stream))
                        {
                            int ipType = reader.ReadByte();//IP类型
                            string type_number = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(16)).Replace(@"\u0000", "").Replace("", "").Trim();//机型编码
                            string lan_ip = String.Join(".", reader.ReadBytes(4));//局域网IP
                            string server_ip = String.Join(".", reader.ReadBytes(4));//服务器IP
                            string subnet_mask = String.Join(".", reader.ReadBytes(4));//子网掩码
                            string gateway = String.Join(".", reader.ReadBytes(4));//网关
                            int lan_port = BitConverter.ToInt32(reader.ReadBytes(4), 0);//局域网端口
                            string dns = String.Join(".", reader.ReadBytes(4));//DNS
                            string software_version = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(20)).Replace(@"\u0000", "").Replace("", "").Trim();//软件版本号
                            int year = reader.ReadByte();
                            int month = reader.ReadByte();
                            int day = reader.ReadByte();
                            int hour = reader.ReadByte();
                            int minute = reader.ReadByte();
                            int second = reader.ReadByte();
                            string rcuTime = string.Format("20{0}-{1}-{2} {3}:{4}:{5}", year, month, day, hour, minute, second);
                            //logger.Error("rcu time:" + rcuTime);
                            DateTime rcu_time = DateTime.Now;
                            DateTime.TryParse(rcuTime, out rcu_time);
                            string launcher_version = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(20)).Replace(@"\u0000", "").Replace("", "").Trim();//Launcher版本
                            string mac = BitConverter.ToString(reader.ReadBytes(6));//MAC
                            long hotel_code = Tools.Byte4ToLong(reader.ReadBytes(4));//项目编码
                            int host_id = BitConverter.ToInt32(reader.ReadBytes(4), 0);//房号ID
                            int roomtype_id = BitConverter.ToInt32(reader.ReadBytes(4), 0);//房型ID
                            string setting_version = String.Join(".", reader.ReadBytes(4));//配置版本号
                            int room_status_id = BitConverter.ToInt32(reader.ReadBytes(4), 0);//房态
                            byte[] season = reader.ReadBytes(4);//季节
                            StringBuilder sbSeason = new StringBuilder();
                            sbSeason.Append((season[0] >> 0) & 3);
                            sbSeason.Append((season[0] >> 2) & 3);
                            sbSeason.Append((season[0] >> 4) & 3);
                            sbSeason.Append((season[0] >> 6) & 3);

                            sbSeason.Append((season[1] >> 0) & 3);
                            sbSeason.Append((season[1] >> 2) & 3);
                            sbSeason.Append((season[1] >> 4) & 3);
                            sbSeason.Append((season[1] >> 6) & 3);

                            sbSeason.Append((season[2] >> 0) & 3);
                            sbSeason.Append((season[2] >> 2) & 3);
                            sbSeason.Append((season[2] >> 4) & 3);
                            sbSeason.Append((season[2] >> 6) & 3);

                            int lock_status = BitConverter.ToInt32(reader.ReadBytes(4), 0);//锁定状态
                            long set_expiration_time = BitConverter.ToUInt32(reader.ReadBytes(4), 0);//授权时间戳
                            long expiration_time = BitConverter.ToUInt32(reader.ReadBytes(4), 0);//授权到期时间戳
                            string roomnumber = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(16)).Replace(@"\u0000", "").Replace("", "").Trim();//房号备注
                            string roomtype = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(16)).Replace(@"\u0000", "").Replace("", "").Trim();//房型备注
                            string room_remark = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(96)).Replace(@"\u0000", "").Replace("", "").Trim();//房间备注
                            string core = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(64)).Replace(@"\u0000", "").Replace("", "").Trim();//MCU机型名称
                            string model = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(64)).Replace(@"\u0000", "").Replace("", "").Trim();//中控机型名称
                            string hotel_name = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(32)).Replace(@"\u0000", "").Replace("", "").Trim();//配置数据酒店名称
                            string roomtype_remark = Encoding.GetEncoding("GBK").GetString(reader.ReadBytes(32)).Replace(@"\u0000", "").Replace("", "").Trim();//配置数据房型别名
                            var hostRCU = HostRCURepository.GetByHostID(host_id);
                            if (hostRCU == null)
                            {
                                hostRCU = new HostRCU();
                            }
                            hostRCU.HotelID = host.SysHotel.ID;
                            hostRCU.IPType = ipType;
                            hostRCU.TypeNumber = type_number;
                            hostRCU.LanIP = lan_ip;
                            hostRCU.ServerIP = server_ip;
                            hostRCU.SubnetMask = subnet_mask;
                            hostRCU.Gateway = gateway;
                            hostRCU.LanPort = lan_port;
                            hostRCU.DNS = dns;
                            hostRCU.Version = software_version;
                            hostRCU.RunTime = (rcu_time.Year < 1800 ? DateTime.Now : rcu_time);
                            hostRCU.LauncherVersion = launcher_version;
                            hostRCU.MAC = mac;
                            hostRCU.HotelCode = hotel_code.ToString();
                            hostRCU.HostID = host_id;
                            hostRCU.RoomTypeID = roomtype_id;
                            hostRCU.ConfigVersion = setting_version.Substring(0, 6);

                            var TTT = new Tuple<Host, string>(host, hostRCU.ConfigVersion);
                            Task.Factory.StartNew((State) =>
                                {
                                    var NNN = (Tuple<Host, string>)State;
                                    BarData bbb = new BarData();
                                    bbb.HostID = NNN.Item1.ID;
                                    //这里才是真正的版本数据
                                    string output = HostSearchReceiver.NormalizeVersion(NNN.Item2);
                                    bbb.ConfiguraVersion = output;
                                    UploadCurrentVersionReceiver.UP_Grade_Json(NNN.Item1, bbb);
                                }, TTT);

                            hostRCU.RoomStatusID = room_status_id;

                            #region 更新缓存
                            ////host_take.HotelID = host.SysHotel.ID;
                            //host_take.IPType = ipType;
                            ////host_take.TypeNumber = type_number;
                            //host_take.LanIP = lan_ip;
                            //host_take.ServerIP = server_ip;
                            //host_take.SubnetMask = subnet_mask;
                            //host_take.Gateway = gateway;
                            //host_take.LanPort = lan_port;
                            //host_take.DNS = dns;
                            //host_take.Version = software_version;
                            //host_take.RunTime = (rcu_time.Year < 1800 ? DateTime.Now : rcu_time);
                            //host_take.LauncherVersion = launcher_version;
                            //host_take.MAC = mac;
                            //host_take.SysHotel.Code = hotel_code.ToString();
                            //host_take.ID = host_id;
                            //host_take.RoomType.ID = roomtype_id;
                            //host_take.ConfigVersion = setting_version.Substring(0, 5);
                            //host_take.RoomStatus.ID = room_status_id;
                            //host_take.Season = sbSeason.ToString();
                            //host_take.LockStatus = lock_status;


                            //host_take.RoomNumber = roomnumber;
                            //host_take.Model = model;
                            //host_take.UpgradeTime = DateTime.Now;
                            #endregion


                            var roomStatus = RoomStatusRepository.Get(room_status_id);
                            if (roomStatus != null)
                            {
                                hostRCU.RoomStatus = roomStatus.Name;
                            }
                            hostRCU.Season = sbSeason.ToString();
                            hostRCU.LockStatus = lock_status;
                            switch (expiration_time)
                            {
                                case 0://永久
                                    hostRCU.ExpireTime = Convert.ToDateTime("2100-12-31");
                                    hostRCU.SetExpireTime = TimeHelper.ToDateTime(set_expiration_time);

                                    break;
                                case 65535://未设置当永久
                                    hostRCU.ExpireTime = Convert.ToDateTime("2100-12-31");

                                    break;
                                default:
                                    hostRCU.ExpireTime = TimeHelper.ToDateTime(expiration_time);
                                    hostRCU.SetExpireTime = TimeHelper.ToDateTime(set_expiration_time);
                                    break;
                            }


                            hostRCU.RoomNumber = roomnumber;
                            hostRCU.RoomType = roomtype;
                            hostRCU.RoomRemark = room_remark;
                            hostRCU.Core = core;
                            hostRCU.Model = model;
                            hostRCU.HotelName = hotel_name;
                            hostRCU.RoomTypeRemark = roomtype_remark;
                            hostRCU.UpdateTime = DateTime.Now;

                            HostRepository.SetModelAndLauncher(host, hostRCU.ConfigVersion, software_version, lan_ip, lan_port, model, launcher_version, hostRCU.ExpireTime, hostRCU.SetExpireTime);

                            HostRCURepository.SaveOrUpdate(hostRCU);

                            //logger.Error(string.Format("酒店({0})客房({1})主机已同步信息，Model：{2}，Launcher：{3}", host.SysHotel.Name + host.SysHotel.Code, host.RoomNumber, model, launcher_version));

                            #region 寄存器读取（弃用）
                            /*int count = reader.ReadByte();//个数
                            reader.ReadBytes(4);
                            string lan_ip = String.Join(".", reader.ReadBytes(4));//局域网IP
                            reader.ReadBytes(4);
                            int lan_port = BitConverter.ToInt32(reader.ReadBytes(4), 0);//局域网端口
                            reader.ReadBytes(4);
                            string subnet_mask = String.Join(".", reader.ReadBytes(4));//子网掩码
                            reader.ReadBytes(4);
                            string gateway = String.Join(".", reader.ReadBytes(4));//网关
                            reader.ReadBytes(4);
                            string dns = String.Join(".", reader.ReadBytes(4));//DNS
                            reader.ReadBytes(4);
                            string server_ip = String.Join(".", reader.ReadBytes(4));//服务器IP
                            reader.ReadBytes(4);
                            int server_port = BitConverter.ToInt32(reader.ReadBytes(4), 0);//服务器端口
                            reader.ReadBytes(4);
                            long expiration_time = BitConverter.ToInt32(reader.ReadBytes(4), 0);//授权到期时间戳
                            reader.ReadBytes(4);
                            long set_expiration_time = BitConverter.ToInt32(reader.ReadBytes(4), 0);//设置到期时间戳
                            reader.ReadBytes(4);
                            int ip_way = reader.ReadByte();//IP类型：1自动，2手动
                            reader.ReadBytes(3);
                            reader.ReadBytes(4);
                            string firmware_version = String.Join(".", reader.ReadBytes(4));//固件版本号
                            reader.ReadBytes(4);
                            string setting_version = String.Join(".", reader.ReadBytes(4));//配置版本号
                            reader.ReadBytes(4);
                            byte[] season = reader.ReadBytes(4);//季节
                            StringBuilder sbSeason = new StringBuilder();
                            sbSeason.Append((season[0] >> 0) & 3);
                            sbSeason.Append((season[0] >> 2) & 3);
                            sbSeason.Append((season[0] >> 4) & 3);
                            sbSeason.Append((season[0] >> 6) & 3);

                            sbSeason.Append((season[1] >> 0) & 3);
                            sbSeason.Append((season[1] >> 2) & 3);
                            sbSeason.Append((season[1] >> 4) & 3);
                            sbSeason.Append((season[1] >> 6) & 3);

                            sbSeason.Append((season[2] >> 0) & 3);
                            sbSeason.Append((season[2] >> 2) & 3);
                            sbSeason.Append((season[2] >> 4) & 3);
                            sbSeason.Append((season[2] >> 6) & 3);

                            logger.Error(string.Format("count:{0},server_ip:{1},expiration_time:{2},ip_way:{3},firmware_version:{4},setting_version:{5},season:{6}",
                                count, server_ip, expiration_time, ip_way, firmware_version, setting_version, sbSeason.ToString()));

                            switch (expiration_time)
                            {
                                case 0://永久
                                    host.ExpireTime = Convert.ToDateTime("2999-12-31");
                                    host.SetExpireTime = TimeHelper.ToDateTime(set_expiration_time.ToString());
                                    break;
                                case 65535://未设置
                                    host.ExpireTime = host.SetExpireTime = null;
                                    break;
                                default:
                                    host.ExpireTime = TimeHelper.ToDateTime(expiration_time.ToString());
                                    host.SetExpireTime = TimeHelper.ToDateTime(set_expiration_time.ToString());
                                    break;
                            }
                            host.LanIP = lan_ip;
                            host.LanPort = lan_port;
                            host.SubnetMask = subnet_mask;
                            host.Gateway = gateway;
                            host.DNS = dns;
                            host.ServerIP = server_ip;
                            host.ServerPort = server_port;
                            host.IPType = ip_way;
                            //host.Version = firmware_version;
                            //host.ConfigVersion = setting_version;
                            host.Season = sbSeason.ToString();
                            HostRepository.Update(host);*/
                            #endregion
                        }
                    }
                }
                catch (Exception ex)
                {
                    logger.Error(string.Format("解释酒店({0})客房({1})主机信息失败，原因：{2}，数据：{3}", host.SysHotel.Name + host.SysHotel.Code, host.RoomNumber, ex.ToString(), msg));
                }
            }
        }

        public override CommandType CommandType
        {
            get { return CommandType.RCUInfo; }
        }
    }

}
