using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Threading;
using ChuPiao.Common.Core.Utils;
using ChuPiao.Common.Enums;
using log4net;

namespace ChuPiao.AutoPrint.Machine.Printer
{
    /// <summary>
    /// 打印机客户端
    /// </summary>
    public class PrinterClient : IPrinterClient
    {
        private Queue<byte[]> _waitPrintQueue=new Queue<byte[]>();
        /// <summary>
        /// 等待打印的数据队列
        /// </summary>
        public Queue<byte[]> WaitPrintQueue
        {
            get { return _waitPrintQueue; }
            set { _waitPrintQueue = value; }
        }

        /// <summary>
        /// 添加电子票文件
        /// </summary>
        /// <param name="ticketFilePath"></param>
        public void AddFile(string ticketFilePath)
        {
            if (!File.Exists(ticketFilePath))
            {
                Log.Info(string.Concat("文件不存在，请检查！",ticketFilePath));
                return;
            }

            string ticketFileText = File.ReadAllText(ticketFilePath);
            AddFileText(ticketFileText);
        }

        /// <summary>
        /// 添加电子票文件(非加密)
        /// </summary>
        /// <param name="ticketFilePath"></param>
        public void AddUnDecryptFile(string ticketFilePath)
        {
            if (!File.Exists(ticketFilePath))
            {
                Log.Info(string.Concat("文件不存在，请检查！", ticketFilePath));
                return;
            }

            byte[] ticketByteArr = File.ReadAllBytes(ticketFilePath);
            AddBytes(ticketByteArr);
        }

        /// <summary>
        /// 添加电子票文本
        /// </summary>
        /// <param name="ticketFileText"></param>
        public void AddFileText(string ticketFileText)
        {
            byte[] ticketByteArr = TicketTextUtil.DecryptAndDecompress(ticketFileText);
            AddBytes(ticketByteArr);
        }

        /// <summary>
        /// 添加电子票字节数组
        /// </summary>
        /// <param name="ticketByteArr"></param>
        public void AddBytes(byte[] ticketByteArr)
        {
            lock (WaitPrintQueue)
            {
                WaitPrintQueue.Enqueue(ticketByteArr);
            }
            //_wait4Job.Set();
        }


        private ILog _log;
        /// <summary>
        /// 日志记录器
        /// </summary>
        public ILog Log
        {
            get { return _log; }
            set { _log = value; }
        }

        private SerialPort _printerPort;
        /// <summary>
        /// 端口
        /// </summary>
        public SerialPort PrinterPort
        {
            get { return _printerPort; }
            set { _printerPort = value; }
        }

        private string _port;
        /// <summary>
        /// 端口号
        /// </summary>
        public string Port
        {
            get { return _port; }
            set { _port = value; }
        }

        private int _portBps;
        /// <summary>
        /// 端口波特率
        /// </summary>
        public int PortBps
        {
            get { return _portBps; }
            set { _portBps = value; }
        }

        private PrinterPortType _printerPortType;
        /// <summary>
        /// 打印机端口类型
        /// </summary>
        public PrinterPortType PrinterPortType
        {
            get { return _printerPortType; }
            set { _printerPortType = value; }
        }


        //虚拟键盘控制线程
        private Thread _printerThread;
        //是否停止
        private bool _isStop = true;

        private EventWaitHandle _wait4Job = new EventWaitHandle(true, EventResetMode.ManualReset);
        /// <summary>
        /// 初始化
        /// </summary>
        public void Initialize()
        {
            WaitPrintQueue=new Queue<byte[]>();
            if (PrinterPortType==PrinterPortType.ComPort)
            {
                _printerPort = new SerialPort(Port, PortBps, Parity.None);
                string strMsg = string.Concat("打印机客户端初始化成功。端口号：", _printerPort.PortName, " 波特率：", PortBps);
                Log.Info(strMsg);
            }
            _printerThread = new Thread(new ThreadStart(DoTask));
        }

        private void DoTask()
        {
            while (!_isStop)
            {
                try
                {
                    if (WaitPrintQueue.Count > 0)
                    {
                        byte[] bytes;
                        lock (WaitPrintQueue)
                        {
                            bytes = WaitPrintQueue.Dequeue();
                        }
                        switch (PrinterPortType)
                        {
                            case PrinterPortType.ComPort:
                                Log.Info("串口打印电子票 长度：" + bytes.Length);
                                WriteFileToComPrint(bytes);
                                Thread.Sleep(1000);
                                //Application.DoEvents();
                                break;
                            case PrinterPortType.ParallelPort:
                                Log.Info("并口打印电子票 长度：" + bytes.Length);
                                WriteFileToParallelPrint(bytes);
                                Thread.Sleep(1000);
                                //Application.DoEvents();
                                break;
                            case PrinterPortType.UsbPort:
                                break;
                        }
                    }
                    
                }
                catch (Exception exception)
                {
                    Log.Info(string.Concat("打印电子票异常。错误信息：",exception.Message));
                }
                Thread.Sleep(1000);
                //Application.DoEvents();
                //if (WaitPrintQueue.Count < 1)
                //{
                //    _wait4Job.Reset();
                //    _wait4Job.WaitOne();
                //}
            }
        }


        /// <summary>
        /// 向com口发送打印数据
        /// </summary>
        /// <param name="arr"></param>
        private void WriteFileToComPrint(byte[] arr)
        {
            //模拟彩票机发送准备数据
            /*byte[] send = new byte[3];
            send[0] = 16;
            send[1] = 4;
            send[2] = 1;
            PrinterPort.Write(send, 0, 3);
            Thread.Sleep(10);

            send[2] = 2;
            PrinterPort.Write(send, 0, 3);
            Thread.Sleep(10);

            send[2] = 3;
            PrinterPort.Write(send, 0, 3);
            Thread.Sleep(10);

            send[2] = 4;
            PrinterPort.Write(send, 0, 3);
            Thread.Sleep(10);*/
            Log.Info("打印数据 端口号" + Port + " 长度" + arr.Length);
            PrinterPort.Write(arr, PrinterPort.BytesToWrite, arr.Length);
        }
        /// <summary>
        /// 向并口发送打印数据
        /// </summary>
        /// <param name="arr"></param>
        private void WriteFileToParallelPrint(byte[] arr)
        {
            Log.Info("打印数据 端口号"+Port+" 长度"+arr.Length);
            POSPrinter posPrinter = new POSPrinter(Port);
            bool result= posPrinter.PrintByte(arr);
            Log.Info("打印数据执行结果 "+result);
        }


        /// <summary>
        /// 启动
        /// </summary>
        public void Start()
        {
            _isStop = false;
            if (PrinterPortType == PrinterPortType.ComPort)
            {
                if (!_printerPort.IsOpen)
                {
                    _printerPort.Open();
                }
            }
            if (_printerThread != null && _printerThread.ThreadState != ThreadState.Running)
            {
                _printerThread.Start();
            }
            Log.Info(string.Concat("打印机客户端启动成功。端口号：", Port));
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            _isStop = true;
            if (PrinterPortType == PrinterPortType.ComPort)
            {
                if (_printerThread != null)
                {
                    if (_printerThread.ThreadState == ThreadState.Running)
                    {
                        _printerThread.Join();
                    }
                    _printerThread.Abort();
                }
                _printerPort.Close();
                _printerPort.Dispose();
                Log.Info(string.Concat("打印机客户端停止成功。端口号：", _printerPort.PortName));
            }
        }
    }
}
