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 Scale
    {
        #region 클래스 변수 선언
        /// <summary>
        /// 전자저울과의 RS232 통신을 위한 시리얼포트 객체
        /// </summary>
        private SerialPort m_cSerialPort = null;
        /// <summary>
        /// 전자저울 이벤트 수신 후 처리할 작업용 스레드 작업(라벨프린터 출력)
        /// </summary>
        private BackgroundWorker bw = null;
        #endregion 클래스 변수 선언

        #region 생성자
        public Scale()
        {
            bw = new BackgroundWorker();
        }
        #endregion 생성자

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

            try
            {
                if (m_cSerialPort != null)
                {
                    //grayber@20180307 시리얼 포트 flush 추가 start  - Open 함수 Input Output 버퍼 삭제 (주석처리)
                    //m_cSerialPort.DiscardInBuffer();
                    //m_cSerialPort.DiscardOutBuffer();
                    //grayber@20180307 시리얼 포트 flush 추가 end
                    m_cSerialPort.Close();
                    System.Threading.Thread.Sleep(50);
                    m_cSerialPort = null;
                }

                if (m_cSerialPort == null)
                {
                    m_cSerialPort = new SerialPort();
                    if (m_cSerialPort == null)
                    {
                        UserLog.WriteLogFile(UserCom.LOG_ERROR,
                                             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 = Encoding.ASCII;
                    m_cSerialPort.WriteBufferSize = 512;
                    m_cSerialPort.PortName = sSerialPort;
                    m_cSerialPort.BaudRate = (int)lBaudrate;
                    m_cSerialPort.DataBits = 7;
                    m_cSerialPort.StopBits = StopBits.One;
                    m_cSerialPort.Parity = Parity.Even;
                    m_cSerialPort.Handshake = Handshake.None;
                    m_cSerialPort.ReadTimeout = 5000;
                    m_cSerialPort.WriteTimeout = 5000;

                    m_cSerialPort.Open();
                    if (m_cSerialPort.IsOpen == false)
                    {
                        UserLog.WriteLogFile(UserCom.LOG_ERROR,
                                             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;
                    }

                    // BackgroundWorker 이벤트 함수 등록
                    bw.DoWork += DeviceEventHandler;
                    bRet = true;
                }
            }
            catch (Exception ex)
            {
                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 (함수명))
                                     ex.Message);
            }

            return bRet;
        }

        public bool CloseScale()
        {
            bool bRet = false;
            try
            {
                if (m_cSerialPort == null)
                {
                    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 (함수명))
                                         "Close fail(m_cSerialPort_Scale == null)");
                    return bRet;
                }
                //grayber@20180307 시리얼 포트 flush 추가 start  - Close 함수 Input Output 버퍼 삭제 
                m_cSerialPort.DiscardInBuffer();
                m_cSerialPort.DiscardOutBuffer();
                //grayber@20180307 시리얼 포트 flush 추가 end
                
                m_cSerialPort.Close();
                bRet = true;
                //grayber@20180307 시리얼 포트 flush 추가 start - try 문 밖으로 이동 (기존)
                //m_cSerialPort = null;
                //grayber@20180307 시리얼 포트 flush 추가 end
                // BackgroundWorker 이벤트 함수 제거
                bw.DoWork -= DeviceEventHandler;
            }
            catch (Exception ex)
            {
                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 (함수명))
                                     ex.Message);
            }
            //grayber@20180307 시리얼 포트 flush 추가 start - try 문 밖으로 이동 (변경)
            m_cSerialPort = null;
            //grayber@20180307 시리얼 포트 flush 추가 end

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

        #region SerialPort Alive 체크
        public bool IsPortOpend()
        {
            bool bRet = false;
            try
            {
                if(m_cSerialPort == null)
                {
                    return false;
                }

                if(m_cSerialPort.IsOpen == false)
                {
                    return false;
                }

                bRet = true;
            }
            catch(Exception ex)
            {
                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 (함수명))
                                     ex.Message);
                bRet = false;
            }

            return bRet;
        }
        #endregion 

        #region SerialPort 이벤트
        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort serialPort = (SerialPort)sender;
            string sHeader = "";

            try
            {
                if ((SerialPort)sender == m_cSerialPort)
                {
                    if (!bw.IsBusy)
                    {
                        // 데이터의 Terminator는 개행문자(\r\n)이므로 개행문자 까지 값을 읽는 ReadLine으로 수신
                        string sScaleData = serialPort.ReadLine();
                        sHeader = sScaleData.Substring(0, 2);

                        // ST:계량모드, QT:계수모드, US:데이터가 안정되지 않다, OL:데이터가 오버되어 있다.(계량범위를 넘었다.)
                        if (sHeader.Equals("ST"))
                        {
                            bw.RunWorkerAsync(sScaleData);
                        }
                        else if (sHeader.Equals("QT"))
                        {

                        }
                        else
                        {

                        }

                        //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 start
#if true // 로그추가
                        //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 (함수명))
                                         "▶▶ " + "Recv: " + "[" + sScaleData + "]");
#endif
                        //grayber@20171222 저울,라벨프린터, PoleDisplay 디버그 로그 추가 end
                    }
                    else
                    {
                        UserLog.WriteLogFile(UserCom.LOG_ERROR,
                                             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 (함수명))
                                             "저울 이벤트 처리 전 이벤트 발생 불가");
                    }
                }
            }
            catch (Exception ex)
            {
                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 (함수명))
                                     ex.Message);
            }
        }

        private void serialPort_PinChanged(object sender, SerialPinChangedEventArgs e)
        {

        }

        private void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {

        }
        #endregion SerialPort 이벤트

        #region Event Handler
        private void DeviceEventHandler(object sender, DoWorkEventArgs e)
        {
            string sScaleData = "";
            string sHeader = "";
            string sWeight = "";
            string sUnit = "";
            string sItemNm = "";
            bool bPrintYn = false;

            try
            {
                // Ex) ST,+00000.00__g
                sScaleData = (string)e.Argument;

                sHeader = sScaleData.Substring(0, 2);
                sWeight = sScaleData.Substring(3, 9);
                sUnit = sScaleData.Substring(12, 3).Trim();
                bPrintYn = GetItemNameByWeight(Convert.ToInt32(sWeight), ref sItemNm);

                // 저울 입력 이벤트 전달
                if (MeasuringMain.m_delegateScaleDev != null)
                    MeasuringMain.m_delegateScaleDev(bPrintYn, Convert.ToInt32(sWeight), sUnit, sItemNm);
                else
                {
                    UserLog.WriteLogFile(UserCom.LOG_ERROR,
                                         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 (함수명))
                                         "MeasuringMain.m_delegateScaleDev is null.");
                }

                // 저울 입력 데이터 전달
                if(MeasuringMain.m_delegateScaleDevRaw != null)
                {
                    MeasuringMain.m_delegateScaleDevRaw(sScaleData);
                }
                else
                {
                    UserLog.WriteLogFile(UserCom.LOG_ERROR,
                                         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 (함수명))
                                         "MeasuringMain.m_delegateScaleDevRaw is null.");
                }
            }
            catch (Exception ex)
            {
                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 (함수명))
                                     ex.Message);
            }
        }
        #endregion Event Handler

        #region 중량데이터로 상품명 얻기
        /// <summary>
        /// 측정된 중량으로 상품명 가져오기
        /// </summary>
        /// <param name="iWeight"></param>
        /// <param name="sItemNm"></param>
        /// <returns></returns>
        private bool GetItemNameByWeight(int iWeight, ref string sItemNm)
        {
            bool bIsOk = false;
            sItemNm = string.Empty;
            try
            {
                if (iWeight >= 236 && iWeight <= 335)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0545);
                    bIsOk = false;
                }
                
                //else if (iWeight >= 336 && iWeight <= 434)
                //{
                //    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0545);
                //    bIsOk = true;
                //}
                //else if (iWeight >= 435 && iWeight <= 534)
                //{
                //    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0546);
                //    bIsOk = true;
                //}
                //#10856] (신규) [BR] 저울 중량 라벨프린터 양식 변경
                //스타워즈 파인트 제외
                else if (iWeight >= 336 && iWeight <= 534)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0545);
                    bIsOk = true;
                }
                else if (iWeight >= 545 && iWeight <= 642)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0547);
                    bIsOk = false;
                }
                else if (iWeight >= 643 && iWeight <= 742)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0547);
                    bIsOk = true;
                }
                else if (iWeight >= 889 && iWeight <= 988)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0548);
                    bIsOk = false;
                }
                else if (iWeight >= 989 && iWeight <= 1088)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0548);
                    bIsOk = true;
                }
                //grayber@20180213 [BR] 핸드팩 중량 출력 대상 제품 추가 요청 start
                // 추가
                else if (iWeight >= 1104 && iWeight <= 1199)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_1095);
                    bIsOk = true;
                }
                // 기존
                //else if (iWeight >= 1137 && iWeight <= 1236)
                // 변경
                else if (iWeight >= 1200 && iWeight <= 1236)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0549);
                    bIsOk = false;
                }
                //grayber@20180213 [BR] 핸드팩 중량 출력 대상 제품 추가 요청 end
                
                else if (iWeight >= 1237 && iWeight <= 1536)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0549);
                    bIsOk = true;
                }
                else if (iWeight >= 1700 && iWeight <= 1999)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0550);
                    bIsOk = false;
                }
                else if (iWeight >= 2000 && iWeight <= 2300)
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0550);
                    bIsOk = true;
                }
                else
                {
                    sItemNm = MessageManager.GetLabelMessage(POS_MESSAGE.LABEL.MSG_0551);
                    bIsOk = false;
                }
            }
            catch (Exception ex)
            {
                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 (함수명))
                                     ex.Message);
            }

            return bIsOk;
        }
        #endregion
    }
}
