using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Common;
using Dao;
using RCUHost.Protocols;
using CommonEntity;

namespace RCUHost.Implement
{
    public abstract class GenericReceiverBase : IReceiver
    {

        #region Static Memberss

        private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(GenericReceiverBase));
        private static readonly Object _locker = new object();
        protected static ushort frameNo = 0;

        #endregion

        #region Privates Properties

        private IHostServer hostServer;
        private ISysSettingRepository sysSettingRepository;
        public ISysSystemLogsRepository SysSystemLogsRepository { get; set; }
        /// <summary>
        /// 服务器通信IP
        /// </summary>
        private string messageIP = "0.0.0.0";
        /// <summary>
        /// 服务器通信端口
        /// </summary>
        private int messagePort = 3389;
        /// <summary>
        /// 组播地址
        /// </summary>
        private string multicastIP = "239.7.8.9";
        /// <summary>
        /// RCU主机通信端口，组播端口
        /// </summary>
        private int mulitcastPort = 3341;
        private string ftpServer = "106.75.37.225";
        private ushort ftpPort = 21;
        private string ftpName = "blw";
        private string ftpPassword = "blw@123";


        #endregion

        #region Public Properties

        public IHostServer HostServer
        {
            get { return this.hostServer; }
            set
            {
                this.hostServer = value;
                //this.hostServer.BeforeStart += new EventHandler(hostServer_BeforeStart);
                //this.hostServer.AfterStart += new EventHandler(hostServer_AfterStart);
            }
        }
        public ISysSettingRepository SysSettingRepository
        {
            get { return this.sysSettingRepository; }
            set
            {
                this.sysSettingRepository = value;
                this.multicastIP = SysSettingRepository.GetValue("MulticastIP").ToString();
                this.mulitcastPort = Convert.ToInt32(SysSettingRepository.GetValue("MulticastPort"));
                this.messageIP = SysSettingRepository.GetValue("MessageIP").ToString();
                this.messagePort = Convert.ToInt32(SysSettingRepository.GetValue("MessagePort"));

                this.ftpServer = SysSettingRepository.GetValue("FTPServer").ToString();
                this.ftpPort = Convert.ToUInt16(SysSettingRepository.GetValue("FTPPort"));
                this.ftpName = SysSettingRepository.GetValue("FTPName").ToString();
                this.ftpPassword = SysSettingRepository.GetValue("FTPPassword").ToString();
            }
        }

        /// <summary>
        /// 服务器通信IP，默认 0.0.0.0
        /// </summary>
        public string MessageIP
        {
            get { return this.messageIP; }
        }
        /// <summary>
        /// 服务器通信端口，默认3389
        /// </summary>
        public int MessagePort
        {
            get { return this.messagePort; }
        }
        /// <summary>
        /// 组播地址，默认 239.7.8.9
        /// </summary>
        public string MulticastIP
        {
            get { return this.multicastIP; }
        }
        /// <summary>
        /// RCU主机通信端口，组播端口，默认 3341
        /// </summary>
        public int MulticastPort
        {
            get { return this.mulitcastPort; }
        }
        public string FTPServer
        {
            get { return this.ftpServer; }
        }
        public ushort FTPPort
        {
            get { return this.ftpPort; }
        }
        public string FTPName
        {
            get { return this.ftpName; }
        }
        public string FTPPassword
        {
            get { return this.ftpPassword; }
        }
        /// <summary>
        /// 命令类型
        /// </summary>
        public abstract CommandType CommandType { get; }

        #endregion

        /// <summary>
        /// 处理数据
        /// </summary>
        /// <param name="context"></param>
        public virtual void Process(ReceiverContext context)
        {

        }

        public static bool DealWwith(ReceiverContext context)
        {
            string HostNumberOnly = context.SystemHeader.Value.HostNumber.ToString();
            var UUU = context.SystemHeader.Value;
            string IP_PORTStr = context.RemoteEndPoint.ToString();
            if (UUU.CmdType == 0x02)
            {
                //如果公告的帧号和要处理的不一致就直接返回
                //ushort CurrentFrameNO = context.SystemHeader.Value.FrameNo;
                //string PublicPop = CacheKey.PublicKeyboard + "_" + IP_PORTStr;
                //object ooo = MemoryCacheHelper.Get(PublicPop);
                //if (ooo != null)
                //{
                //    ushort Newlast = Convert.ToUInt16(ooo);
                //    if (Newlast != CurrentFrameNO)
                //    {
                //        return false;
                //    }
                //}
                //如果超过2秒就不再处理了
                //string ShiJianLanJie = CacheKey.SyncTimeIntercept + "_" + HostNumberOnly;
                string ShiJianLanJie = CacheKey.TimeIntercept + "_" + HostNumberOnly;
                object VVV = MemoryCacheHelper.Get(ShiJianLanJie);
                if (VVV == null)
                {
                    string hotelCode = context.SystemHeader.Value.HostNumber.ToHotelCode().ToString();//获取酒店编码
                    string RegisterKey1 = "RoomStatusTimeOutDrop";
                    RCUHost.RCUHostCommon.tools.LanJieData(RegisterKey1, hotelCode);
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 获取下一个帧号：小于32767
        /// </summary>
        /// <returns></returns>
        protected ushort GetNextFrameNo()
        {
            lock (_locker)
            {
                if (frameNo >= 0x7EFF)//32767
                {
                    frameNo = 0;
                }
                else
                {
                    frameNo++;
                }
            }
            return frameNo;
        }
        /// <summary>
        /// HostServer 启动之前调用
        /// </summary>
        /// <param name="hostServer"></param>
        protected virtual void HostServer_BeforeStart(HostServer hostServer)
        {
        }
        /// <summary>
        /// HostServer 启动之后调用
        /// </summary>
        /// <param name="hostServer"></param>
        protected virtual void HostServer_AfterStart(HostServer hostServer)
        {
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="hostNumber"></param>
        protected void Send(byte[] data, string hostNumber, string mac)
        {
            try
            {
                string ipAndPort = CSRedisCacheHelper.Get<string>(hostNumber, mac);
                if (!string.IsNullOrEmpty(ipAndPort))
                {
                    //这里判断0x0F
                    //AA 55 30 00 54 33 53 41 0F 15 71 FF FF FF FF 
                    //05 
                    //07 01 00 00 00 80 
                    //07 02 00 00 00 80 
                    //07 03 00 00 00 80 
                    //07 04 00 00 00 80 
                    //07 05 00 00 00 80 CA 7C
                    //AA 55 11 00 54 33 53 41 0F 15 71 3D 04 92 D0 6B 15 

                    var cmdtype = data[8];
                    var device_count = data[15];
                    if (cmdtype == 0x0F)
                    {
                        byte[] framenolist = data.Skip(7).Take(2).ToArray();
                        var zhenhao = BitConverter.ToUInt16(framenolist, 0);
                        string RoomNUMBER = CSRedisCacheHelper.HMGet<string>(5, CacheKey.RoomNumber_HostNumber, hostNumber)[0];
                        if (!string.IsNullOrEmpty(RoomNUMBER))
                        {
                            var code = Tools.HostNumberToHotelCode(hostNumber);
                            DeviceActionData d1 = new DeviceActionData();
                            d1.ts_ms = Tools.GetUnixTime();
                            d1.hotel_id = code.ToString();
                            d1.room_id = RoomNUMBER;
                            d1.device_id = hostNumber;
                            d1.frame_id = zhenhao;
                            d1.cmd_word = "0F";
                            d1.udp_raw = data;
                            d1.direction = "下发";

                            List<ts_controlitem> lll3 = new List<ts_controlitem>();

                            int skip = 16;
                            for (int i = 1; i <= device_count; i++)
                            {
                                var t1 = data.Skip(skip + (i - 1) * 6).Take(6).ToArray();
                                ts_controlitem ts = new ts_controlitem();
                                ts.dev_addr = t1[0];
                                ts.dev_type = t1[1];
                                ts.dev_loop = t1[2];
                                ts.type_h = t1[3];
                                ts.type_l = BitConverter.ToInt16(new byte[] { t1[5], t1[4] }, 0);
                                lll3.Add(ts);
                            }
                            d1.control_list = lll3;
                            d1.report_count = lll3.Count;


                            string sss = Newtonsoft.Json.JsonConvert.SerializeObject(d1);
                            CSRedisCacheHelper.Publish("redis-0X36-0X0F", sss);
                        }
                    }


                    HostServer.Send(data, ipAndPort.ToString().Split(':')[0], int.Parse(ipAndPort.ToString().Split(':')[1]));
                }
            }
            catch (Exception ex)
            {
                logger.Error("发送："+ex.Message);
                logger.Error(ex.StackTrace);
            }
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="endPoint"></param>
        protected void Send(byte[] data, IPEndPoint endPoint)
        {
            HostServer.Send(data, endPoint);
        }
        /// <summary>
        /// 发送数据并添加到队列
        /// </summary>
        /// <param name="data"></param>
        /// <param name="hostNumber"></param>
        protected void SendAndPushCommandQueue(byte[] data, string hostNumber, string mac)
        {
            string ipAndPort = CSRedisCacheHelper.Get<string>(hostNumber, mac);
            if (!string.IsNullOrEmpty(ipAndPort))
            {
                HostServer.SendAndPushCommandQueue(data, ipAndPort.ToString().Split(':')[0], Convert.ToInt32(ipAndPort.ToString().Split(':')[1]));
            }
        }
        /// <summary>
        /// 回复下位机命令
        /// </summary>
        /// <param name="context"></param>
        protected void Reply(ReceiverContext context)
        {
            var headerLen = StructConverter.SizeOf(context.SystemHeader);
            var headerData = new byte[headerLen + 2];
            Array.Copy(context.Data, headerData, headerLen);
            headerData[2] = 0x11;
            headerData[3] = 0x00;
            Send(headerData, context.RemoteEndPoint);
        }

        /// <summary>
        /// 创建 SystemHeader
        /// </summary>
        /// <returns></returns>
        protected SystemHeader CreateSystemHeader()
        {
            return CreateSystemHeader(0);
        }
        /// <summary>
        /// 创建 SystemHeader
        /// </summary>
        /// <param name="dataLength">数据包长度，不包含头部长度</param>
        /// <returns></returns>
        protected SystemHeader CreateSystemHeader(int dataLength)
        {
            return CreateSystemHeader(CommandType, dataLength);
        }
        /// <summary>
        /// 创建 SystemHeader
        /// </summary>
        /// <param name="commandType">命令类型</param>
        /// <param name="dataLength">数据包长度，不包含头部长度</param>
        /// <returns></returns>
        protected SystemHeader CreateSystemHeader(CommandType commandType, int dataLength)
        {
            var systemHeader = new SystemHeader();
            systemHeader.Signature = SystemHeader.SIGNATURE;
            systemHeader.FrameLength = (ushort)(StructConverter.SizeOf(systemHeader) + dataLength);
            systemHeader.SystemID = SystemHeader.SYSTEM_ID.ToCharArray();
            systemHeader.CmdType = (byte)commandType;
            systemHeader.FrameNo = GetNextFrameNo();
            systemHeader.HostNumber = new HostNumber { NBuild = 0xFF, NFloor = 0xFF, NRoom = 0xFF, NUnit = 0xFF };
            return systemHeader;
        }
        /// <summary>
        /// 创建 DeviceHeader
        /// </summary>
        /// <returns></returns>
        protected DeviceHeader CreateDeviceHeader()
        {
            return new DeviceHeader
            {
                NodeAddr = 0x00,
                CmdType = (ushort)IPAddress.HostToNetworkOrder((short)this.CommandType),
                AskAck = 0x01,
                RoomNumber = new HostNumber
                {
                    NBuild = 0xff,
                    NFloor = 0xff,
                    NRoom = 0xff,
                    NUnit = 0xff
                }
            };
        }
        /// <summary>
        /// 记录操作日志
        /// </summary>
        /// <param name="authorityID">权限ID</param>
        /// <param name="action">动作</param>
        /// <param name="detail">详细</param>
        /// <param name="result">操作结果</param>
        /// <param name="account">帐号</param>
        /// <param name="hotelID">所属酒店ID</param>
        protected void SaveSystemLog(int authorityID, string action, string detail, string result, string account, string ip, int hotelID)
        {
            try
            {
                Domain.SysSystemLogs entity = new Domain.SysSystemLogs();
                entity.ID = 0;
                entity.AuthorityID = authorityID;
                entity.Action = action;
                entity.Detail = detail;
                entity.Result = result;
                entity.Account = account;
                entity.IP = ip;
                entity.Time = DateTime.Now;
                entity.HotelID = hotelID;

                SysSystemLogsRepository.Save(entity);
            }
            catch (Exception ex) { logger.Error("保存操作日志失败：" + ex.ToString()); }
        }

        #region Private Methods

        private void hostServer_BeforeStart(object sender, EventArgs e)
        {
            HostServer_BeforeStart(sender as HostServer);
        }

        private void hostServer_AfterStart(object sender, EventArgs e)
        {
            HostServer_AfterStart(sender as HostServer);
        }

        #endregion
    }
}
