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

using Cosmos.Common;
using Cosmos.UserFrame;

namespace Cosmos.OLEDevice
{
    /// <summary>
    /// Line Display 제어 CLASS
    /// </summary>
    public class DeviceLineDisplay : ILineDisplayUs
    {
        #region VctCdpStdJo.dll 제어 함수
        [DllImport("VctCdpStdJo.dll")]
        public static extern int CdpOpen();

        [DllImport("VctCdpStdJo.dll")]
        public static extern int CdpWrite(string sMsg, int iAmt);

        [DllImport("VctCdtpStdJo.dll")]
        public static extern int CdpClose();
        #endregion
        #region 클래스 변수 선언
        /// <summary>
        /// StateServer Object (StateServer 객체)
        /// </summary>
        public StateServer StateObject = (StateServer)StateServer.GetInstance();

        public PosStatus m_cPosStatus = new PosStatus();
        /// <summary>
        /// Device 상태 정보 객체
        /// </summary>
        public DeviceStatus devStatus = new DeviceStatus();

        /// <summary>
        /// RS232통신을 위한 시리얼포트 객체
        /// </summary>
        private SerialPort m_serialPort = null;

        //private BackgroundWorker bw = null;
        #endregion 클래스 변수 선언

        #region 생성자 / 초기화
        public DeviceLineDisplay()
        {
            try
            {
                m_cPosStatus = (PosStatus)StateObject.POS;
                devStatus = (DeviceStatus)StateObject.DEVICE;

                DeviceStatusInit();
                //bw = new BackgroundWorker();
            }
            catch(Exception ex)
            {

            }
        }        

        private void DeviceStatusInit()
        {
            devStatus.LineDisplay.Open = false;
            devStatus.LineDisplay.Status = string.Empty;
        }
        #endregion 생성자 / 초기화

        #region OPEN / CLOSE 처리
        public bool OpenDevice(string sSerialPort, long lBaudrate)
        {
            bool bRet = false;
            try
            {
                if (m_serialPort != null)
                {
                    m_serialPort.Close();
                    System.Threading.Thread.Sleep(50);
                    m_serialPort = null;
                }

                if (m_serialPort == null)
                {
                    m_serialPort = new SerialPort();
                    if (m_serialPort == null)
                    {
                        devStatus.Scale.Open = false;
                        devStatus.Scale.Status = "SERIAL PORT ERROR";
                        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 (함수명))
                                             devStatus.Scale.Status);
                        return bRet;
                    }

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

                    m_serialPort.WriteBufferSize = 1024 * 1024;
                    m_serialPort.PortName = sSerialPort;
                    m_serialPort.BaudRate = (int)lBaudrate;
                    m_serialPort.ReadTimeout = 500;
                    m_serialPort.WriteTimeout = 2000;

                    if(m_cPosStatus.Base.OleCdpModel == PosConst.POS_DEVICE_LIST.CDP._0_TOSHIBA)
                    {
                        m_serialPort.Parity = Parity.Odd;
                        m_serialPort.DataBits = 8;
                        m_serialPort.StopBits = StopBits.One;
                        m_serialPort.Handshake = Handshake.RequestToSend;
                        m_serialPort.RtsEnable = true;
                        m_serialPort.DtrEnable = true;
                    }
                    else
                    {
                        m_serialPort.Parity = Parity.None;
                        m_serialPort.DataBits = 8;
                        m_serialPort.StopBits = StopBits.One;
                        m_serialPort.Handshake = Handshake.None;
                        m_serialPort.RtsEnable = false;
                        m_serialPort.DtrEnable = false;
                    }

                    m_serialPort.Open();
                    if (m_serialPort.IsOpen == false)
                    {
                        devStatus.LineDisplay.Open = false;
                        devStatus.LineDisplay.Status = "SERIAL PORT OPEN ERROR";
                        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 (함수명))
                                             devStatus.Scale.Status);
                        return bRet;
                    }

                    devStatus.LineDisplay.Open = true;
                    devStatus.LineDisplay.Status = "SUCCESS";

                    bRet = true;
                }
                else
                {
                    devStatus.LineDisplay.Open = false;
                    devStatus.LineDisplay.Status = "SERIAL PORT ERROR";
                    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 (함수명))
                                         devStatus.Scale.Status);
                    return bRet;
                }
            }
            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;
        }


        public bool CloseDevice()
        {
            bool bRet = false;

            try
            {
                if (m_serialPort == 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_serialPort == null)");
                    return bRet;
                }

                m_serialPort.Close();
                bRet = true;
                m_serialPort = null;
                devStatus.LineDisplay.Status = "CLOSE";
                devStatus.LineDisplay.Open = false;
            }
            catch (Exception ex)
            {
                devStatus.LineDisplay.Status = "CLOSE EXCEPTION";
                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;
        }
        #endregion OPEN / CLOSE 처리

        #region LineDisplay 제어 
        public bool DisplayText(int iAmt, string sMsg)
        {
            bool bRet = false;

            try
            {
                DisplayClear();

                if (m_cPosStatus.Base.OleCdpModel == PosConst.POS_DEVICE_LIST.CDP._0_TOSHIBA)
                {
                    TransmitCommand(PosConst.CDP_COMMAND.LINE_START_1);
                    TransmitCommand(Convert.ToString(iAmt));
                    TransmitCommand(PosConst.CDP_COMMAND.LINE_START_2);
                    TransmitCommand(sMsg);
                }
                else if (m_cPosStatus.Base.OleCdpModel == PosConst.POS_DEVICE_LIST.CDP._1_XN)
                {
                    TransmitCommand(string.Format("{0, -20}", Convert.ToString(iAmt)));
                    TransmitCommand(string.Format("{0, -20}", sMsg));
                }
            }
            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;
        }

        public bool DisplayClear()
        {
            bool bRet = false;

            try
            {
                if(m_cPosStatus.Base.OleCdpModel == PosConst.POS_DEVICE_LIST.CDP._0_TOSHIBA)
                {
                    TransmitCommand(PosConst.CDP_COMMAND.LINE_CLEAR);
                }
                else if(m_cPosStatus.Base.OleCdpModel == PosConst.POS_DEVICE_LIST.CDP._1_XN)
                {
                    TransmitCommand(PosConst.CDP_COMMAND.LINE_CLEAR_XN);
                }
            }
            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;
        }
        #endregion

        private void TransmitCommand(byte[] aCmd, bool bSleepOn = true)
        {
            if (m_serialPort.IsOpen == true)
            {
                int iOffset = 0;
                //int iReadBuf = 2048;
                int iReadBuf = m_serialPort.WriteBufferSize;

                while (true)
                {
                    if (iOffset >= aCmd.Length)
                    {
                        break;
                    }
                    if (iReadBuf + iOffset > aCmd.Length)
                    {
                        iReadBuf = aCmd.Length - iOffset;
                    }
                    m_serialPort.Write(aCmd, iOffset, iReadBuf);

                    iOffset += iReadBuf;
                    System.Threading.Thread.Sleep(10);
                }
                //m_serialPort.Write(Encoding.Default.GetString(aCmd, 0, aCmd.Length));

                if (bSleepOn == true) System.Threading.Thread.Sleep(30);
            }
        }

        private void TransmitCommand(string sMsg, bool bSleepOn = true)
        {
            if(m_serialPort.IsOpen == true)
            {
                m_serialPort.WriteLine(sMsg);

                if (bSleepOn == true) System.Threading.Thread.Sleep(30);
            }
        }
    }
}
