using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using ChuPiao.AutoPrint.Machine;
using ChuPiao.AutoPrint.Machine.Printer;
using ChuPiao.Common.Core.Utils;
using ChuPiao.Common.Enums;
using ChuPiao.Common.Models;
using ChuPiao.Common.Utils;
using ChuPiao.Office.Services;
using log4net;
using ChuPiao.AutoPrint.Services.AutoPrint;
using ChuPiao.AutoPrint.Configuration;
using System.Text;

namespace ChuPiao.AutoPrint.Services
{
    public static class LotMachineService
    {

        static bool initialized;
        private static Dictionary<string,ILotMachine> _lotMachineList=new Dictionary<string, ILotMachine>();

        public static Dictionary<string, ILotMachine> LotMachineList
        {
            get { return _lotMachineList; }
            set { _lotMachineList = value; }
        }

        public static void InitializeLotMachine()
        {
            try
            {
                if (!initialized)
                {
                    initialized = true;

                    //构造M_ComputerEntity对象
                    M_ComputerEntity computer = new M_ComputerEntity();
                    Dictionary<string, MachineXmlEntity> machineXmlEntityDic = new Dictionary<string, MachineXmlEntity>();
                    foreach (MachineXmlEntity _entity in MachineXmlConfig.GetMachineList())
                    {
                        M_MachineEntity _machine = new M_MachineEntity();
                        _machine.M_Number = _entity.M_Number;
                        _machine.M_Salt = _entity.M_Salt;
                        _machine.M_ZxPassword = _entity.M_ZxPassword;
                        _machine.M_VirtualKeyboardPort = _entity.M_VirtualKeyboardPort;
                        _machine.M_VirtualKeyboardPortBps = _entity.M_VirtualKeyboardPortBps;
                        _machine.M_VirtualPrinterPort = _entity.M_VirtualPrinterPort;
                        _machine.M_VirtualPrinterPortBps = _entity.M_VirtualPrinterPortBps;
                        _machine.M_InputDeviceType = 100;
                        _machine.M_KeyboardType = 1002;
                        _machine.M_Type = 1001;
                        _machine.M_AllowPaperout = _entity.M_AllowPaperout;
                       // _machine.M_AllowPaperout = false;
                        _machine.M_HasJc = _entity.M_HasJc;
                        _machine.M_IsSimulate = _entity.M_IsSimulate;
                        _machine.M_IsAutoClearTotal = _entity.M_IsAutoClearTotal;
                        //_machine.M_IsAutoEncash = _entity.M_IsAutoEncash;
                        _machine.M_IsAutoEncash = false;
                        _machine.M_LotStr = string.IsNullOrEmpty(_entity.M_Lots) ? "911,701," : _entity.M_Lots;

                        computer.MachineList.Add(_machine);
                        machineXmlEntityDic.Add(_entity.M_Number, _entity);
                    }
                  
                    //方便其它程序用到出票电脑这个实体
                    AutoPrintServiceManager.Computer = computer;
                    //方便设置彩票机属性，并且本地化
                    AutoPrintServiceManager.MachineXmlEntityDic = machineXmlEntityDic;

                    if (computer != null)
                    {
                        if (computer.MachineList.Count > 0)
                        {
                            computer.MachineList.Sort(delegate(M_MachineEntity machine1, M_MachineEntity machine2)
                            {
                                return machine1.M_Number.CompareTo(machine2.M_Number); 
                            });

                            ConfigLog4net(computer.MachineList);

                            LotMachineFactory lotMachineFactory = new LotMachineFactory();
                            /*从配置文件加载配置*/
                            M_MachineConfigTemplateService machineConfigTemplateService = new M_MachineConfigTemplateService();
                            EnumDescription[] machineTypes = EnumDescription.GetFieldTexts(typeof(MachineType));

                            /*从配置文件加载配置*/
                            foreach (M_MachineEntity machineEntity in computer.MachineList)
                            {

                                /*从配置文件加载配置*/
                                foreach (EnumDescription machineType in machineTypes)
                                {
                                    if (machineType.EnumValue == machineEntity.M_Type)
                                    {
                                        M_MachineConfigEntity machineConfig = machineConfigTemplateService.GetBasicMachineConfig(machineType.FieldName);
                                        List<M_MachineModeConfigEntity> machineModeConfigs = machineConfigTemplateService.GetBasicMachineModeConfigs(machineType.FieldName);

                                        machineEntity.MachineConfigEntity = machineConfig;
                                        machineEntity.MachineModeConfigs = new SortedDictionary<int, M_MachineModeConfigEntity>();
                                        foreach (M_MachineModeConfigEntity configEntity in machineModeConfigs)
                                        {
                                            machineEntity.MachineModeConfigs.Add(configEntity.C_MacModeId, configEntity);
                                        }
                                    }
                                }
                                /*从配置文件加载配置*/

                                ILotMachine machine = lotMachineFactory.CreateLotMachine(machineEntity.M_Type);
                                //JxTiCaiMachine machine = new JxTiCaiMachine();
                                machine.MachineInfo = machineEntity;
                                machine.Log = log4net.LogManager.GetLogger(machineEntity.M_Number);
                                //machine.PrinterClient = _printerClient;
                                machine.Initialize();
                                //machine.StartDriver();
                                //machine.VirtualPrinter.PrinterClient = _printerClient;
                                _lotMachineList.Add(machineEntity.M_Number, machine);
                            }
                        }
                    }

                    
                }
            }
            catch (Exception exception)
            {
                LoggingService.Info(string.Concat("彩票机初始化异常。错误信息：", exception.ToString()));
                MessageService.ShowMessage(string.Concat("彩票机初始化异常。错误信息：", exception.Message));
            }
            
        }
        public static void StartDriver()
        {
            try
            {
                foreach (KeyValuePair<string, ILotMachine> keyValuePair in _lotMachineList)
                {
                    keyValuePair.Value.StartDriver();
                }
            }
            catch (Exception exception)
            {
                MessageService.ShowMessage(string.Concat("彩票机启动异常。错误信息：", exception.Message));
            }
        }
        public static void StopDriver()
        {
            try
            {
                foreach (KeyValuePair<string, ILotMachine> keyValuePair in _lotMachineList)
                {
                    keyValuePair.Value.StopDriver();
                }
            }
            catch (Exception exception)
            {
                MessageService.ShowMessage(string.Concat("彩票机停止异常。错误信息：", exception.Message));
            }
        }
        public static void SaveLastPrintCounter()
        {

            try
            {
                //M_MachineService machineService = new M_MachineService();
                foreach (ILotMachine lotMachine in _lotMachineList.Values)
                {
                    lotMachine.MachineInfo.M_LastPrintCounter = lotMachine.VirtualPrinter.LastPrintCounter;
                    //machineService.UpdateLastPrintCounter(lotMachine.MachineInfo);
                    //lotMachine.Log.Info("保存彩票机最后一张票计数器：" + lotMachine.MachineInfo.M_LastPrintCounter);
                }
                
            }
            catch (Exception exception)
            {
                LoggingService.Info(string.Concat("保存彩票机最后一张票计数器异常。错误信息：", exception.Message));
            }
        }
        private static void ConfigLog4net(List<M_MachineEntity> machineList)
        {
            //log4net.Config.XmlConfigurator.Configure(new FileInfo(Application.StartupPath + "/configs/log4net.xml"));
            string logpath = Log4netUtil.FileAppendPath("default");
            string machinelogpath = logpath.Remove(logpath.IndexOf("Autoprintlot"));

            //日志log4net：根据彩票机动态添加logger，读同目录下的log4net.xml文件，保存到debug/log4netTemp.xml供log4net初始化
            XmlDocument doc = new XmlDocument();
            doc.Load(Application.StartupPath + "/configs/log4net.xml");
            XmlNode nodelog4net = doc.GetElementsByTagName("log4net")[0];

            foreach (M_MachineEntity machine in machineList)
            {
                //建fileappender
                XmlElement eleappender = doc.CreateElement("appender");
                eleappender.SetAttribute("name", machine.M_Number + "FileAppender");
                eleappender.SetAttribute("type", "log4net.Appender.RollingFileAppender");
                XmlElement elefile = doc.CreateElement("file");
                elefile.SetAttribute("value", machinelogpath + machine.M_Number + "\\");
                XmlElement eleappendToFile = doc.CreateElement("appendToFile");
                eleappendToFile.SetAttribute("value", "true");
                XmlElement elerollingStyle = doc.CreateElement("rollingStyle");
                elerollingStyle.SetAttribute("value", "Date");
                XmlElement eledatePattern = doc.CreateElement("datePattern");
                eledatePattern.SetAttribute("value", "yyyy-MM-dd/'default'/HH'.txt'");
                XmlElement elestaticLogFileName = doc.CreateElement("staticLogFileName");
                elestaticLogFileName.SetAttribute("value", "false");
                //XmlElement eleencoding = doc.CreateElement("encoding");
                //eleencoding.SetAttribute("value", "unicodeFFFE");
                XmlElement elelayout = doc.CreateElement("layout");
                elelayout.SetAttribute("type", "log4net.Layout.PatternLayout");
                XmlElement eleconversionPattern = doc.CreateElement("conversionPattern");
                eleconversionPattern.SetAttribute("value", "%date [%thread] %-5level %logger [%property{NDC}] - %message%newline");
                elelayout.AppendChild(eleconversionPattern);
                eleappender.AppendChild(elefile);
                eleappender.AppendChild(eleappendToFile);
                eleappender.AppendChild(elerollingStyle);
                eleappender.AppendChild(eledatePattern);
                eleappender.AppendChild(elestaticLogFileName);
                //eleappender.AppendChild(eleencoding);
                eleappender.AppendChild(elelayout);
                //创建logger
                XmlElement elelogger = doc.CreateElement("logger");
                elelogger.SetAttribute("name", machine.M_Number);
                XmlElement eleappenderref = doc.CreateElement("appender-ref");
                eleappenderref.SetAttribute("ref", machine.M_Number + "FileAppender");
                elelogger.AppendChild(eleappenderref);
                //把建的fileappender和logger加到log4net结点下
                nodelog4net.AppendChild(elelogger);
                nodelog4net.AppendChild(eleappender);
            }
            doc.Save(Application.StartupPath + "/configs/log4netTemp.xml");

            //初始化log4net
            //log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(Application.StartupPath + "/configs/log4netTemp.xml"));
            LogUtil.Setup(Application.StartupPath + "/configs/log4netTemp.xml");
        }

        /// <summary>
        /// 打印电子票
        /// </summary>
        /// <param name="macnumber">机器号</param>
        /// <param name="filepath">电子票文件路径</param>
        /// <param name="isencrypt">是否加密文件</param>
        public static void PrintETicket(string macnumber,string filepath,bool isencrypt)
        {
            try
            {
                //if (IsUseComputerPrinter)
                //{
                //    if (isencrypt)
                //    {
                //        PrinterClient.AddFile(filepath);
                //    }
                //    else
                //    {
                //        PrinterClient.AddUnDecryptFile(filepath);
                //    }
                //}
                //else
                //{
                    byte[] bytes;
                    if(isencrypt)
                    {
                        bytes = TicketTextUtil.DecryptAndDecompress(File.ReadAllText(filepath));
                    }
                    else
                    {
                        bytes = File.ReadAllBytes(filepath);
                    }
                    LoggingService.Info(string.Concat(macnumber, "开始打印电子票：", filepath));
                    PrintETicket(macnumber,bytes);
                //}
            }
            catch (Exception exception)
            {
                LoggingService.Error(string.Concat("打印电子票异常。错误信息：",exception));
            }
        }
        /// <summary>
        /// 打印电子票
        /// </summary>
        /// <param name="macnumber">机器号</param>
        /// <param name="bytes">电子票内容</param>
        public static void PrintETicket(string macnumber,byte[] bytes)
        {
            try
            {
                //if (IsUseComputerPrinter)
                //{
                //    PrinterClient.AddBytes(bytes);
                //}
                //else
                //{
                    //if(string.IsNullOrEmpty(macnumber))
                    //{
                    //    foreach (KeyValuePair<string, ILotMachine> keyValuePair in LotMachineList)
                    //    {
                    //        if (keyValuePair.Value.MachineInfo.M_Status == (int)MachineStatusEnum.Stopped)
                    //        {
                    //            macnumber = keyValuePair.Value.MachineInfo.M_Number;
                    //            break;
                    //        }
                    //    }
                    //}
                    //if (string.IsNullOrEmpty(macnumber))
                    //{
                    //    throw new Exception("没有停止状态的彩票机可用于打印票文件");
                    //}
                    //ChuPiao.Common.Communication.CpdJson.Packs.P12014PrintTicketFile reqPack = new ChuPiao.Common.Communication.CpdJson.Packs.P12014PrintTicketFile();
                    //reqPack.MacNumber = macnumber;
                    //reqPack.PrnText = HexStringUtil.ByteToString(bytes);
                    //ChuPiao.Common.Communication.CpdJson.PackRetBase packRetBase = ChuPiao.Common.Communication.CpdJson.PackManager.Instance.Transaction(macnumber, reqPack,LotMachineList[macnumber].Log);
                    //if (packRetBase == null)
                    //{
                    //    throw new Exception(string.Concat("执行命令失败。机器号：", macnumber));
                    //}
                    //if (packRetBase.ReturnCode != 0)
                    //{
                    //    throw new Exception(string.Concat("彩票机返回错误编码：", packRetBase.ReturnCode, " 错误信息：", packRetBase.ReturnMessage));
                    //}

                //if (IsUseComputerPrinter)
                //{
                //    PrinterClient.AddBytes(bytes);
                //}
                //else
                //{
                    ILotMachine lotMachine = LotMachineService.LotMachineList[macnumber];
                    lotMachine.VirtualPrinter.PrinterPort.Write(bytes, 0, bytes.Length);
                //}

                LoggingService.Info(string.Concat(macnumber, "打印电子票成功，字节长度：",bytes.Length));
                //}
            }
            catch (Exception exception)
            {
                LoggingService.Error(string.Concat("打印电子票异常。错误信息：", exception));
            }
        }
    }
}
