using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;

using Cosmos.Common;
using Cosmos.UserFrame;
using Cosmos.BaseFrame;

namespace Cosmos.KPS
{
    class SerialPrint
    {
        PrinterCommand prtCmd = new PrinterCommand();

        private SerialPort ComPort;
        public bool IsPortOpened
        {
            get { if (ComPort == null) { return false; } else { return ComPort.IsOpen; } }
        }

        #region Printer OPEN / CLOSE
        public int DeviceOpen(string sPortNum, int iBaudRate)
        {
            int iRet = UserCom.NG;
            try
            {                
                if(ComPort == null)
                {
                    ComPort = new SerialPort();

                    ComPort.DataReceived += new SerialDataReceivedEventHandler(ComPort_DataReceived);
                    ComPort.PinChanged += new SerialPinChangedEventHandler(ComPort_PinChanged);
                    ComPort.ErrorReceived += new SerialErrorReceivedEventHandler(ComPort_ErrorReceived);

                    ComPort.NewLine = "\r\n";
                    ComPort.Encoding = System.Text.Encoding.GetEncoding("ks_c_5601-1987");
                }

                if (!IsPortOpened) DeviceClose();

                ComPort.WriteBufferSize = 1024 * 1024;
                ComPort.PortName = sPortNum;
                ComPort.BaudRate = iBaudRate;
                ComPort.DataBits = 8;
                ComPort.StopBits = StopBits.One;
                ComPort.Parity = Parity.None;
                ComPort.Handshake = Handshake.RequestToSend;

                ComPort.ReadTimeout = 500;
                ComPort.WriteTimeout = 2000;

                ComPort.RtsEnable = true;
                ComPort.DtrEnable = true;

                if(!ComPort.IsOpen)
                {
                    ComPort.Open();
                }

                iRet = ComPort.IsOpen == true ? UserCom.OK : UserCom.NG;

                return iRet;
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
                return -99;
            }
        }

        public int DeviceClose()
        {
            int iRet = UserCom.NG;
            try
            {
                if(!IsPortOpened)
                {
                    return UserCom.OK;
                }

                ComPort.Close();
                if(IsPortOpened)
                {
                    System.Threading.Thread.Sleep(1000);
                    ComPort.Close();
                }

                iRet = IsPortOpened == false ? UserCom.OK : UserCom.NG;

                return iRet;
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_DEBUG,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
                return -99;
            }
        }
        #endregion

        #region Serial Port Event
        void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            
        }

        void ComPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
        }

        void ComPort_PinChanged(object sender, SerialPinChangedEventArgs e)
        {
        }
        #endregion

        #region Status Check
        public int PrinterStatusCheckBySerial(string sType)
        {
            int iRet = UserCom.NG;
            string sResp = "";

            try
            {
                #region Printer CHK1
                if(sType == "CHK1")
                {
                    // 프린터 초기화
                    TransmitCommand(PosConst.ESCP_COMMAND.INITIALIZE_PRINTER);
                    System.Threading.Thread.Sleep(50);

                    // Cover Check
                    TransmitCommand(PosConst.ESCP_COMMAND.TRANSMIT_OFFLINE_STATUS);
                    System.Threading.Thread.Sleep(50);
                    sResp = ComPort.ReadExisting();
                    if(sResp.Length > 0)
                    {
                        byte[] respByte = Encoding.Default.GetBytes(sResp);
                        if(respByte[0] == PosConst.ESCP_COMMAND.STATUS_OK[0])
                        {
                            iRet = UserCom.OK;
                        }
                        else
                        {
                            iRet = UserCom.NG;
                            UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                                 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                                 System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                                 "COVER Opened");
                        }
                    }
                    return iRet;
                }
                #endregion

                #region Printer CHK2
                if(sType == "CHK2")
                {
                    // 프린터 초기화
                    TransmitCommand(PosConst.ESCP_COMMAND.INITIALIZE_PRINTER);
                    System.Threading.Thread.Sleep(50);

                    // Paper Check
                    TransmitCommand(PosConst.ESCP_COMMAND.TRANSMIT_CONTINUOUS_PAPER_DETECTOR_STATUS);
                    System.Threading.Thread.Sleep(50);
                    sResp = ComPort.ReadExisting();
                    if(sResp.Length > 0)
                    {
                        byte[] respByte = Encoding.Default.GetBytes(sResp);
                        if(respByte[0] == PosConst.ESCP_COMMAND.STATUS_OK[0])
                        {
                            iRet = UserCom.OK;
                        }
                        else
                        {
                            iRet = UserCom.NG;

                            String sRecvData = Encoding.Default.GetString(respByte);

                            string NEAR_END = Encoding.Default.GetString(new byte[] { 0x1E });
                            string NOT_PRESENT = Encoding.Default.GetString(new byte[] { 0x72 });

                            string sErrMsg = "";
                            if (sRecvData == NEAR_END) sErrMsg = "PAPER_NEAR_END";
                            else if (sRecvData == NOT_PRESENT) sErrMsg = "PAPER_NOT_PRESENT";
                            else sErrMsg = "ERC_ERROR";

                            UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                                 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                                 System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                                 sErrMsg);
                        }
                    }
                    return iRet;
                }
                #endregion
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     "StatusCheck 실패");
            }
            return iRet;
        }
        #endregion

        #region 공통 모듈
        private void TransmitCommand(byte[] aCmd)
        {
            if(IsPortOpened)
            {
                ComPort.Write(aCmd, 0, aCmd.Length);
            }
        }
        #endregion

        #region Cut Paper
        public bool CutPaper(int LineFeedCnt)
        {
            long nRet = -1;
            try
            {
                for (int i = 0; i < LineFeedCnt; i++)
                {
                    TransmitCommand(PosConst.ESCP_COMMAND.LINE_FEED);
                }

                TransmitCommand(PosConst.ESCP_COMMAND.PAPER_CUT);
                System.Threading.Thread.Sleep(10);
                TransmitCommand(PosConst.ESCP_COMMAND.LINE_FEED);
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     "Cut Paper Exception");
            }
            return nRet == BaseCom.OK ? true : false;
        }
        #endregion

        #region 문자열 출력
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="eAlignment"></param>
        /// <param name="eVerticalSize"></param>
        /// <param name="eHorizontalSize"></param>
        /// <param name="eBold"></param>
        /// <param name="eTextUnderLine"></param>
        /// <param name="eTextReverseMode"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, PrinterCommand.Alignment eAlignment, PrinterCommand.CharactersizeV eVerticalSize, PrinterCommand.CharactersizeH eHorizontalSize, PrinterCommand.TextBold eBold, PrinterCommand.TextUnderLine eTextUnderLine, PrinterCommand.TextReverseMode eTextReverseMode, bool bLineFeed)
        {
            bool bRet = false;
            string sCmdctrlTmp = "";

            try
            {
                // 확대 Command를 설정
                sCmdctrlTmp = GetCharactersizeCmd(eVerticalSize, eHorizontalSize);

                // UnerLine
                sCmdctrlTmp += GetUnderLineCmd(eTextUnderLine);

                // Bold
                sCmdctrlTmp += GetBoldCmd(eBold);

                // 정렬
                sCmdctrlTmp += GetAlignment(eAlignment);

                // Reverse
                sCmdctrlTmp += GetReverseCmd(eTextReverseMode);

                // 출력
                byte[] byteCmdctrl = Encoding.Default.GetBytes(sCmdctrlTmp);
                TransmitCommand(byteCmdctrl);       // Command 전송

                byte[] byteData = Encoding.Default.GetBytes(sValue);
                TransmitCommand(byteData);          // 출력 Data 전송

                if(bLineFeed == true)
                {
                    TransmitCommand(PosConst.ESCP_COMMAND.LINE_FEED);

                }

                bRet = true;
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
            }

            return bRet;
        }
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="eAlignment"></param>
        /// <param name="eVerticalSize"></param>
        /// <param name="eHorizontalSize"></param>
        /// <param name="eBold"></param>
        /// <param name="eTextUnderLine"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, PrinterCommand.Alignment eAlignment, PrinterCommand.CharactersizeV eVerticalSize, PrinterCommand.CharactersizeH eHorizontalSize, PrinterCommand.TextBold eBold, PrinterCommand.TextUnderLine eTextUnderLine, bool bLineFeed)
        {
            return TextPrint(sValue, eAlignment, eVerticalSize, eHorizontalSize, eBold, eTextUnderLine, PrinterCommand.TextReverseMode.Nomal, bLineFeed);
        }
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, bool bLineFeed)
        {
            return TextPrint(sValue, PrinterCommand.Alignment.Left, PrinterCommand.CharactersizeV.V_1, PrinterCommand.CharactersizeH.H_1, PrinterCommand.TextBold.Nomal, PrinterCommand.TextUnderLine.Nomal, PrinterCommand.TextReverseMode.Nomal, bLineFeed);
        }
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="eAlignment"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, PrinterCommand.Alignment eAlignment, bool bLineFeed)
        {
            return TextPrint(sValue, eAlignment, PrinterCommand.CharactersizeV.V_1, PrinterCommand.CharactersizeH.H_1, PrinterCommand.TextBold.Nomal, PrinterCommand.TextUnderLine.Nomal, PrinterCommand.TextReverseMode.Nomal, bLineFeed);
        }
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="eAlignment"></param>
        /// <param name="eVerticalSize"></param>
        /// <param name="eHorizontalSize"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, PrinterCommand.Alignment eAlignment, PrinterCommand.CharactersizeV eVerticalSize, PrinterCommand.CharactersizeH eHorizontalSize, bool bLineFeed)
        {
            return TextPrint(sValue, eAlignment, eVerticalSize, eHorizontalSize, PrinterCommand.TextBold.Nomal, PrinterCommand.TextUnderLine.Nomal, PrinterCommand.TextReverseMode.Nomal, bLineFeed);
        }
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="eAlignment"></param>
        /// <param name="eBold"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, PrinterCommand.Alignment eAlignment, PrinterCommand.TextBold eBold, bool bLineFeed)
        {
            return TextPrint(sValue, eAlignment, PrinterCommand.CharactersizeV.V_1, PrinterCommand.CharactersizeH.H_1, eBold, PrinterCommand.TextUnderLine.Nomal, PrinterCommand.TextReverseMode.Nomal, bLineFeed);
        }
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="eAlignment"></param>
        /// <param name="eTextUnderLine"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, PrinterCommand.Alignment eAlignment, PrinterCommand.TextUnderLine eTextUnderLine, bool bLineFeed)
        {
            return TextPrint(sValue, eAlignment, PrinterCommand.CharactersizeV.V_1, PrinterCommand.CharactersizeH.H_1, PrinterCommand.TextBold.Nomal, eTextUnderLine, PrinterCommand.TextReverseMode.Nomal, bLineFeed);
        }
        /// <summary>
        /// Print Text
        /// </summary>
        /// <param name="sValue"></param>
        /// <param name="eAlignment"></param>
        /// <param name="eTextReverseMode"></param>
        /// <param name="bLineFeed"></param>
        /// <returns></returns>
        public bool TextPrint(string sValue, PrinterCommand.Alignment eAlignment, PrinterCommand.TextReverseMode eTextReverseMode, bool bLineFeed)
        {
            return TextPrint(sValue, PrinterCommand.Alignment.Left, PrinterCommand.CharactersizeV.V_1, PrinterCommand.CharactersizeH.H_1, PrinterCommand.TextBold.Nomal, PrinterCommand.TextUnderLine.Nomal, eTextReverseMode, bLineFeed);
        }

        private string GetCharactersizeCmd(PrinterCommand.CharactersizeV eVerticalSize, PrinterCommand.CharactersizeH eHorizontalSize)
        {
            string sRet = "";

            try
            {
                int Hvalue = 0;
                int Vvalue = 0;

                switch (eVerticalSize)
                {
                    case PrinterCommand.CharactersizeV.V_1: Vvalue = 0; break;
                    case PrinterCommand.CharactersizeV.V_2: Vvalue = 1; break;
                    case PrinterCommand.CharactersizeV.V_3: Vvalue = 2; break;
                    case PrinterCommand.CharactersizeV.V_4: Vvalue = 3; break;
                    case PrinterCommand.CharactersizeV.V_5: Vvalue = 4; break;
                    case PrinterCommand.CharactersizeV.V_6: Vvalue = 5; break;
                    case PrinterCommand.CharactersizeV.V_7: Vvalue = 6; break;
                    case PrinterCommand.CharactersizeV.V_8: Vvalue = 7; break;
                    default: Vvalue = 0; break;
                }

                switch (eHorizontalSize)
                {
                    case PrinterCommand.CharactersizeH.H_1: Hvalue = 16 * 0; break;
                    case PrinterCommand.CharactersizeH.H_2: Hvalue = 16 * 1; break;
                    case PrinterCommand.CharactersizeH.H_3: Hvalue = 16 * 2; break;
                    case PrinterCommand.CharactersizeH.H_4: Hvalue = 16 * 3; break;
                    case PrinterCommand.CharactersizeH.H_5: Hvalue = 16 * 4; break;
                    case PrinterCommand.CharactersizeH.H_6: Hvalue = 16 * 5; break;
                    case PrinterCommand.CharactersizeH.H_7: Hvalue = 16 * 6; break;
                    case PrinterCommand.CharactersizeH.H_8: Hvalue = 16 * 7; break;
                    default: Hvalue = 16 * 0; break;
                }
                sRet = Encoding.Default.GetString(prtCmd.ESC_VHMAG) + Convert.ToChar(Vvalue + Hvalue).ToString();
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
            }

            return sRet;
        }
        /// <summary>
        /// 진한 문자(Bold)
        /// </summary>
        /// <param name="eBold"></param>
        /// <returns></returns>
        private string GetBoldCmd(PrinterCommand.TextBold eBold)
        {
            string sRet = "";
            try
            {
                switch (eBold)
                {
                    case PrinterCommand.TextBold.Nomal: sRet = Encoding.Default.GetString(prtCmd.ESC_BOLD_OFF); break;
                    case PrinterCommand.TextBold.Bold: sRet = Encoding.Default.GetString(prtCmd.ESC_BOLD_ON); break;
                    default: sRet = Encoding.Default.GetString(prtCmd.ESC_BOLD_OFF); break;
                }
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
            }

            return sRet;
        }
        /// <summary>
        /// UnderLine
        /// </summary>
        /// <param name="eUnderLine"></param>
        /// <param name="nDot"></param>
        /// <returns></returns>
        private string GetUnderLineCmd(PrinterCommand.TextUnderLine eUnderLine, int nDot)
        {
            string sRet = "";
            try
            {
                if (eUnderLine == PrinterCommand.TextUnderLine.UnderLine)
                {
                    if (nDot == 2)
                    {
                        sRet = Encoding.Default.GetString(prtCmd.ESC_UNDERLINEON1DOT);
                    }
                    else
                    {
                        sRet = Encoding.Default.GetString(prtCmd.ESC_UNDERLINEON2DOT);
                    }
                }
                else
                {
                    sRet = Encoding.Default.GetString(prtCmd.ESC_UNDERLINEOFF);
                }
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
            }

            return sRet;
        }
        /// <summary>
        /// UnderLine Text
        /// </summary>
        /// <param name="eUnderLine"></param>
        /// <returns></returns>
        private string GetUnderLineCmd(PrinterCommand.TextUnderLine eUnderLine)
        {
            return GetUnderLineCmd(eUnderLine, 1);
        }
        /// <summary>
        /// 반전 텍스트
        /// </summary>
        /// <param name="eTextReverseMode"></param>
        /// <returns></returns>
        private string GetReverseCmd(PrinterCommand.TextReverseMode eTextReverseMode)
        {
            string sRet = "";
            try
            {
                switch (eTextReverseMode)
                {
                    case PrinterCommand.TextReverseMode.ReverseMode: sRet = Encoding.Default.GetString(prtCmd.ESC_REVERSE_MODE_ON); break;
                    default: sRet = Encoding.Default.GetString(prtCmd.ESC_REVERSE_MODE_OFF); break;
                }
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
            }

            return sRet;
        }
        /// <summary>
        /// 정렬 Command를 가져온다.
        /// </summary>
        /// <param name="eAlignment"></param>
        /// <returns></returns>
        private string GetAlignment(PrinterCommand.Alignment eAlignment)
        {
            string sRet = "";
            try
            {
                switch (eAlignment)
                {
                    case PrinterCommand.Alignment.Center:
                        sRet = Encoding.Default.GetString(prtCmd.ESC_CENTER);
                        break;
                    case PrinterCommand.Alignment.Right:
                        sRet = Encoding.Default.GetString(prtCmd.ESC_RIGHT);
                        break;
                    case PrinterCommand.Alignment.Left:
                    default:
                        sRet = Encoding.Default.GetString(prtCmd.ESC_LEFT);
                        break;
                }
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_IOS,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
            }

            return sRet;
        }
        #endregion
    }
}
