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

using Cosmos.CommonManager;
using Cosmos.UserFrame;

namespace Cosmos.Measuring
{
    public class LabelPrinter
    {
        #region 클래스 변수 선언
        private static SerialPort m_cSerialPort = null;
        #endregion 클래스 변수 선언

        #region 생성자
        public LabelPrinter()
        {
            
        }
        #endregion 생성자

        #region OPEN / CLOSE 처리 함수
        public bool OpenLabelPrinter(string sSerialPort, long lBaudrate)
        {
            bool bRet = false;

            try
            {
                #region log
                //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 start
                //grayber@20171222 디버그 로그 추가 - 저울 디버그
                UserLog.WriteLogFile(UserCom.LOG_OP,
                                 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 (함수명))
                                 "▶▶ [OPEN]");
                //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 end
                #endregion
                if (m_cSerialPort != null)
                {
                    //grayber@20180307 시리얼 포트 flush 추가 start - Open 함수 Input Output 버퍼 삭제 (주석처리) 
                    // 추가
                    if (m_cSerialPort.IsOpen != true)   // 시리얼포트 오픈 실패
                    {
                        m_cSerialPort.Open();           // 시리얼포트 오픈
                    }
                    //m_cSerialPort.DiscardOutBuffer();
                    //m_cSerialPort.DiscardInBuffer();
                    //UserLog.WriteLogFile(UserCom.LOG_OP,
                    //                 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 (함수명))
                    //                 "▶▶ [Open InOut Buffer Clear]");

                    bRet = true;
                    //grayber@20180307 시리얼 포트 flush 추가 end
                    return bRet;
                }

                if(m_cSerialPort == null)
                {
                    m_cSerialPort = new SerialPort();
                    if(m_cSerialPort == null)
                    {
                        UserLog.WriteLogFile(UserCom.LOG_IOS,
                                             UserCom.WARNING_LEVEL,
                                             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 (함수명))
                                             "SERIAL PORT ERROR");
                        return bRet;
                    }

                    m_cSerialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
                    m_cSerialPort.PinChanged += new SerialPinChangedEventHandler(serialPort_PinChanged);
                    m_cSerialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);

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

                    m_cSerialPort.WriteBufferSize = 1024 * 1024;
                    m_cSerialPort.PortName = sSerialPort;
                    m_cSerialPort.BaudRate = (int)lBaudrate;
                    m_cSerialPort.DataBits = 8;
                    m_cSerialPort.StopBits = StopBits.One;
                    m_cSerialPort.Parity = Parity.None;
                    m_cSerialPort.Handshake = Handshake.None;
                    m_cSerialPort.ReadTimeout = 500;
                    m_cSerialPort.WriteTimeout = 2000;

                    m_cSerialPort.Open();
                    if(m_cSerialPort.IsOpen == false)
                    {
                        UserLog.WriteLogFile(UserCom.LOG_IOS,
                                             UserCom.WARNING_LEVEL,
                                             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 (함수명))
                                             "SERIAL PORT OPEN ERROR");

                        return bRet;
                    }

                    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);
            }

            #region log
            //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 start
            //grayber@20171222 디버그 로그 추가 - 저울 디버그
            UserLog.WriteLogFile(UserCom.LOG_OP,
                             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 (함수명))
                             "▶▶ [OPEN]" + bRet);

            //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 end
            #endregion
            return bRet;
        }

        public bool CloseLabelPrinter()
        {
            bool bRet = false;
            try
            {
                if (m_cSerialPort == null)
                {
                    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 (함수명))
                                         "Close fail(m_cSerialPort == null)");
                    return bRet;
                }

                //grayber@20180307 시리얼 포트 flush 추가 start - Close 함수 Input Output 버퍼 삭제 
                // 추가
                m_cSerialPort.DiscardOutBuffer();
                m_cSerialPort.DiscardInBuffer();
                //grayber@20180307 시리얼 포트 flush 추가 end

                m_cSerialPort.Close();
                bRet = true;
                //grayber@20180307 시리얼 포트 flush 추가 start - try 문 밖으로 이동 (기존)
                //m_cSerialPort = null;
                //grayber@20180307 시리얼 포트 flush 추가 end

                
            }
            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);
            }

            #region log
            //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 start
            //grayber@20171222 디버그 로그 추가 - 저울 디버그
            UserLog.WriteLogFile(UserCom.LOG_OP,
                             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 (함수명))
                             "▶▶ [CLOSE] Close InOut Buffer Clear :" + bRet);
            //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 end
            #endregion
            //grayber@20180307 시리얼 포트 flush 추가 start - try 문 밖으로 이동 (변경)
            m_cSerialPort = null;
            //grayber@20180307 시리얼 포트 flush 추가 end

            return bRet;
        }
        #endregion OPEN / CLOSE 처리 함수

        #region SerialPort 이벤트
        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort serialPort = (SerialPort)sender;
            byte[] bytRecvBuf = new byte[serialPort.BytesToRead];

            try
            {
                //grayber@20180307 시리얼 포트 flush 추가 start - DataReceived 시리얼 포트 null check 
                // 기존
                //serialPort.Read(bytRecvBuf, 0, bytRecvBuf.Length);
                // 변경
                if (serialPort != null && serialPort.IsOpen == true)    // 시리얼포트 객체 및 오픈 확인
                {
                    serialPort.Read(bytRecvBuf, 0, bytRecvBuf.Length);

                    #region log
                    //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 start
                    UserLog.WriteLogFile(UserCom.LOG_OP,
                                     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 (함수명))
                                     "▶▶ [RECV] " + Encoding.UTF8.GetString(bytRecvBuf));
                    //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 end
                    #endregion
                }
                //grayber@20180307 시리얼 포트 flush 추가 end
            }
            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);
            }
        }

        private void serialPort_PinChanged(object sender, SerialPinChangedEventArgs e)
        {

        }

        private void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {

        }
        #endregion SerialPort 이벤트

        #region 출력 함수
        /// <summary>
        /// 중량 출력
        /// </summary>
        /// <param name="sContent">상품명 : 중량g</param>
        /// <param name="iWeight">중량</param>
        /// <param name="sDateTime">YYYY-MM-DD HH:MM:SS</param>
        /// <param name="sStoreNm">점포명</param>
        public void PrintWeightInfo(string sContent, string sDateTime, string sStoreNm)
        {
            string[] sCommands = null;

            try
            {
                
                sCommands = new string[] { "CLL\r\n"        // 메모리 클리어
                                         , "NEW\r\n"        // 새로운 명령어 시작
                                         , "CLIP ON\r\n"
                                         , "FONT \"HYGothic-Medium\",12\r\n"    
                                         , "NASC 949\r\n"   // intermec 한글폰트 설정
                                         , "PRPOS 0,150\r\n"
                                         , "PRTXT \"" + sContent + "\"\r\n"
                                         , "FONT \"HYGothic-Medium\",9\r\n"    
                                         , "PRPOS 0,110\r\n"
                                         , "PRTXT \"" + sDateTime + "\"\r\n"
                                         , "PRPOS 0,70\r\n"
                                         , "PRTXT \"" + sStoreNm + "\"\r\n"
                                         , "PRPOS 0,30\r\n"
                                         , "PRTXT \"배달은 해피오더 / 1670-3131\"\r\n"                           //#10856_[BR] 저울 중량 라벨프린터 양식 변경_hs
                                         , "PF\r\n" };

                if (sCommands != null)
                    WriteCommand(sCommands);
                
            }
            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);
            }
        }

        public void PrintWeightInfo(string sContent, string sFlavour1, string sFlavour2, string sOrdDateTime, string sPckDateTime)
        {
            string[] sCommands = null;

            try
            {
                // EX)
                //     패밀리 / 980g (5516)
                //     플레이버1/플레이버2/플레이버3
                //     플레이버4/플레이버5/플레이버6
                //
                //     주문 YYYY-MM-DD HH시MM분
                //     포장 YYYY-MM-DD HH시MM분
                sCommands = new string[] { "CLL\r\n"        // 메모리 클리어
                                         , "NEW\r\n"        // 새로운 명령어 시작
                                         , "CLIP ON\r\n"
                                         , "FONT \"HYGothic-Medium\",12\r\n"
                                         , "NASC 949\r\n"
                                         , "PRPOS 0,190\r\n"
                                         , "PRTXT \"" + sContent + "\"\r\n"
                                         , "FONT \"HYGothic-Medium\",9\r\n"   
                                         , "PRPOS 0,150\r\n"
                                         , "PRTXT \"" + sFlavour1 + "\"\r\n"
                                         , "PRPOS 0,110\r\n"
                                         , "PRTXT \"" + sFlavour2 + "\"\r\n"
                                         , "PRPOS 0,50\r\n"
                                         , "PRTXT \"" + sOrdDateTime + "\"\r\n"
                                         , "PRPOS 0,10\r\n"
                                         , "PRTXT \"" + sPckDateTime + "\"\r\n"
                                         , "PF\r\n" };

                if (sCommands != null)
                    WriteCommand(sCommands);
            }
            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);
            }
        }
        #endregion 출력 함수

        #region 명령어 전송 함수
        /// <summary>
        /// 시리얼포트에 명령어를 전송
        /// </summary>
        /// <param name="sCommands"></param>
        private void WriteCommand(string[] sCommands)
        {
            try
            {
                foreach(string cmd in sCommands)
                {
                    m_cSerialPort.Write(cmd);
                }

            }
            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);
            }
        }
        #endregion 명령어 전송 함수
    }
}
