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

using Cosmos.UserFrame;
using Cosmos.Common;
using System.Runtime.InteropServices;

/*-----------------------------------------------------------------------------------------------*/
// 설      명 : CAT 단말기 제어
// 작  성  자 : 
// 변경  이력 : 
/*-----------------------------------------------------------------------------------------------*/
namespace Cosmos.OLEDevice
{
    /// <summary>
    /// CAT 단말기 제어 CLASS
    /// </summary>
    public class DeviceCatTerminal : ICatTerminalUs
    {

        /// <summary>
        /// 단말기와 승인/취소 통신을 처리하는 함수
        /// </summary>
        /// <param name="comport"></param>
        /// <param name="baud"></param>
        /// <param name="input_msg"></param>
        /// <param name="output_msg"></param>
        /// <returns></returns>
        [DllImport("SPCNSecuCAT.dll")]
        public static extern int SPCNSecuCAT_Payment(int comport, int baud, byte[] input_msg, byte[] output_msg);

        /// <summary>
        /// 단말기에 저장된 미전송 내역을 받아오는 함수
        /// </summary>
        /// <param name="comport"></param>
        /// <param name="baud"></param>
        /// <param name="output_msg"></param>
        /// <returns></returns>
        [DllImport("SPCNSecuCAT.dll")]
        public static extern int SPCNSecuCAT_GetRemain(int comport, int baud, byte[] output_msg);

        /// <summary>
        /// 중국 - 샨더 단말기와 승인/취소 통신을 처리하는 함수
        /// </summary>
        /// <param name="comport"></param>
        /// <param name="input_msg"></param>
        /// <param name="output_msg"></param>
        [DllImport("LibSand.dll")]
        public static extern void card_trans(int comport, byte[] input_msg, byte[] output_msg);

        /// <summary>
        /// 중국 - 은련 단말기와 승인/취소 통신을 처리하는 함수
        /// </summary>
        /// <param name="comport"></param>
        /// <param name="input_msg"></param>
        /// <param name="output_msg"></param>
        [DllImport("posinf.dll")]
        public static extern int bankall(byte[] request, byte[] response);

        /// <summary>
        /// StateServer Object (StateServer 객체)
        /// </summary>
        public StateServer StateObject = (StateServer)StateServer.GetInstance();
        /// <summary>
        /// Device 상태 정보 객체
        /// </summary>
        public DeviceStatus m_cdevStatus = null;

        /// <summary>
        /// Pos 상태 정보 객체
        /// </summary>
        public PosStatus m_cPosStatus = null;

        /// <summary>
        /// 생성자
        /// </summary>
        public DeviceCatTerminal()
        {
            try
            {
                m_cPosStatus = (PosStatus)StateObject.POS;
                m_cdevStatus = (DeviceStatus)StateObject.DEVICE;
            }
            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 연결확인
        /// <summary>
        /// 연결확인(가동시 체크)
        /// </summary>
        public bool SPCNSecuCatStatus()
        {
            bool bRet = false;
            string sSendData = string.Empty;
            string sRecvData = string.Empty;

            try
            {
                if (m_cPosStatus.Base.OlePosCATModel == PosConst.CAT_MODEL_DIV._KOR_SPCN)
                {
                    sSendData = CmUtil.RPadH("Z0A0  000000000000000000000000000", 360);
                    if (SPCNSecuCatApprove(sSendData, ref sRecvData) > 0)
                        bRet = true;
                }
                else if (m_cPosStatus.Base.OlePosCATModel == PosConst.CAT_MODEL_DIV._CHN_SAND || m_cPosStatus.Base.OlePosCATModel == PosConst.CAT_MODEL_DIV._CHN_UNION)
                {
                    // 중국산은 상태 체크 없어 패스
                    //if (SPCNSecuCatApprove(sSendData, ref sRecvData) >= 0)
                        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;
        }
        #endregion


        #region 연결 상태 확인 및 CAT 단말기 정보 확인
        /// <summary>
        /// 연결 상태 및 CAT 단말기 정보 확인
        /// </summary>
        public int SPCNSecuCatInfo(string sSendData, ref string sRecvData)
        {
            int nReturn = -99;

            try
            {
                nReturn = SPCNSecuCatApprove(sSendData, ref sRecvData);

            }
            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 nReturn;
        }
        #endregion

        #region 승인/취소 요청
        /// <summary>
        /// 승인/취소 요청
        /// </summary>
        /// <param name="sSendData"></param>
        /// <param name="sRecvData"></param>
        /// <returns></returns>
        public int SPCNSecuCatApprove(string sSendData, ref string sRecvData) 
        {
            int nReturn = -99;

            try
            {

                byte[] bytInputMsg = null;
                byte[] bytOutput = new byte[4096];

                sRecvData = string.Empty;
                Array.Clear(bytOutput, 0, bytOutput.Length);

                bytInputMsg = Encoding.Default.GetBytes(sSendData);

                switch (m_cPosStatus.Base.OlePosCATModel)
                {
                    case PosConst.CAT_MODEL_DIV._KOR_SPCN:
                        {
                            nReturn = SPCNSecuCAT_Payment(CmUtil.IntParse(m_cPosStatus.Base.OlePosCATSerialPortNumber.Replace("COM", "")), (int)m_cPosStatus.Base.OlePosCATSerialBaudRate, bytInputMsg, bytOutput);   // 승인조회

                            if (nReturn < 0)       //승인실퍠
                            {
                                //실패경우
                                sRecvData = ErrCodeToMsg(nReturn);
                            }
                            else
                            {
                                sRecvData = ByteToString(bytOutput);
                            }
                            break;
                        }
                    case PosConst.CAT_MODEL_DIV._CHN_SAND:
                        {
                            // 중국 샨더 단말기
                            card_trans(CmUtil.IntParse(m_cPosStatus.Base.OlePosCATSerialPortNumber.Replace("COM", "")), bytInputMsg, bytOutput);   // 승인조회

                            sRecvData = ByteToString(bytOutput);

                            if (sRecvData.Length > 0) nReturn = 0;
                            break;
                        }
                    case PosConst.CAT_MODEL_DIV._CHN_UNION:
                        {
                            // 중국 은련 단말기
                            bankall(bytInputMsg, bytOutput);   // 승인조회

                            sRecvData = ByteToString(bytOutput);

                            if (sRecvData.Length > 0) nReturn = 0;
                            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 nReturn;
        }
        #endregion


        #region 승인/취소 요청
        /// <summary>
        /// 단말기에 저장된 미전송 내역을 받아오는 함수
        /// </summary>
        /// <param name="sRecvData"></param>
        /// <returns></returns>
        public int SPCNSecuCatRemain(ref string sRecvData)
        {
            int nReturn = -99;

            try
            {
                byte[] bytOutput = new byte[4096];

                sRecvData = string.Empty;
                Array.Clear(bytOutput, 0, bytOutput.Length);

                nReturn = SPCNSecuCAT_GetRemain(CmUtil.IntParse(m_cPosStatus.Base.OlePosCATSerialPortNumber.Replace("COM", "")), (int)m_cPosStatus.Base.OlePosCATSerialBaudRate, bytOutput);

                if (nReturn < 0)       //승인실퍠
                {
                    //실패경우
                    sRecvData = ErrCodeToMsg(nReturn);
                }
                else
                {
                    sRecvData = ByteToString(bytOutput);
                }
            }
            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 nReturn;
        }
        #endregion

        /// <summary>
        /// Byte배열을 string으로 변환 (Byte배열의 null(0x00)값 제거)
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private string ByteToString(byte[] data)
        {
            int inx = Array.FindIndex(data, 0, (x) => x == 0x0);
            if (inx >= 0)
            {
                return Encoding.Default.GetString(data, 0, inx);
            }
            else
            {
                return Encoding.Default.GetString(data);
            }
        }

        /// <summary>
        /// 응답코드 
        /// </summary>
        /// <param name="nErrCode"></param>
        /// <returns></returns>
        private string ErrCodeToMsg(int nErrCode)
        {
            string sMsg = string.Empty;

            try
            {
                switch (nErrCode)
                {
                    case -101: sMsg = "시리얼포트번호오류"; break;
                    case -102: sMsg = "통신속도오류"; break;
                    case -103: sMsg = "전문길이오류"; break;
                    case -210: sMsg = "할부개월오류"; break;
                    case -211: sMsg = "금액봉사료세금오류"; break;
                    case -212: sMsg = "원거래일자오류"; break;
                    case -213: sMsg = "포인트거래구분오류"; break;
                    case -301: sMsg = "거래중카드제거"; break;
                    case -302: sMsg = "단말기 사용자 강제종료"; break;
                    case -303: sMsg = "기타단말기오류"; break;
                    case -304: sMsg = "카드삽입되어있음"; break;
                    case -305: sMsg = "사용자강제취소"; break;
                    case -401: sMsg = "시리얼포트오픈오류"; break;
                    case -402: sMsg = "시리얼쓰기오류"; break;
                    case -403: sMsg = "시리얼읽기오류"; break;
                    case -404: sMsg = "시리얼닫기오류"; break;
                    case -405: sMsg = "시리얼타임아웃"; break;
                    case -411: sMsg = "미전송내역없음"; break;
                    default: sMsg = "정의되어 있지 않은 메세지" + "[" + nErrCode + "]"; break;
                }
            }
            catch { }
            return sMsg;
        }

    }
}
