using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Data;
using System.Runtime.InteropServices;

using Newtonsoft.Json.Linq;

using Cosmos.BaseFrame;
using Cosmos.UserFrame;
using Cosmos.ServiceProvider;
using Cosmos.Common;
using Cosmos.CommonManager;

namespace Cosmos.OLEDevice
{
    /// <summary>
    /// T-PAY BLE Dongle (paygle)
    /// </summary>
    class DeviceTPaygle : ITPaygleUs
    {

        #region ## XPayLib.dll Function
        /// <summary>
        /// 체크인 된 고객리스트를 수신
        /// </summary>
        /// <param name="connectList"></param>
        /// <returns></returns>
        [DllImport("XPayLib.dll")]
        private static extern int GetPOSConnectList(byte[] connectList);

        /// <summary>
        /// 선택고객의 BLE OTB 발급요청(구버전 호환성문제로 유지)
        /// </summary>
        /// <param name="XPT"></param>
        /// <returns></returns>
        [DllImport("XPayLib.dll")]
        private static extern int ReqPOSProvide(byte[] XPT);

        /// <summary>
        ///  선택고객의 BLE OTB 발급요청/수신(폰의 OS별로 지원 가능)
        /// </summary>
        /// <param name="XPT"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        [DllImport("XPayLib.dll")]
        private static extern int ReqPOSProvide2(byte[] XPT, byte[] param);

        /// <summary>
        /// BLE OTB 수신
        /// </summary>
        /// <param name="KeyRlt"></param>
        /// <returns></returns>
        [DllImport("XPayLib.dll")]
        private static extern int GetOTB(byte[] KeyRlt);

        /// <summary>
        /// 수신된 비밀번호를 40Byte 해시코드로 변환
        /// </summary>
        /// <param name="Rlt">HashString 반환버퍼</param>
        /// <param name="param">변환할 비밀번호</param>
        [DllImport("XPayLib.dll")]
        private static extern void PWHashing(byte[] Rlt, byte[] param); 

        /// <summary>
        /// Paygle상태를 체크하고 업데이트가 필요한 경우 업데이트
        /// </summary>
        /// <returns></returns>
        [DllImport("PaygleCheck.dll")]
        private static extern int PaygleCheckProc();

        //#20170906 T페이 고도화 작업 phj, start
        /// 수신된 OTB를 분류 검증 (결제방식, 사전인증 체크 기능)
        /// 입력된 OTB의 유효성과, 선인증여부를 확인합니다.
        /// </summary>
        /// <param name="ClassifyOTB"> 카드번호 </param>
        [DllImport("XPayLib.dll")]
        private static extern int ClassifyOTB(byte[] ClassifyOTB);
        //#20170906 T페이 고도화 작업 phj, end

        #endregion


        private StateServer StateObject = (StateServer)StateServer.GetInstance();   // StateObject : StateServer Object (객체)
        private PosStatus posStatus = new PosStatus();                              // 기본정보 참조
        private DeviceStatus devStatus = new DeviceStatus();                        // 장치정보 참조 

        /// <summary>
        /// 생성자 
        /// </summary>
        public DeviceTPaygle()
        {
            devStatus = (DeviceStatus)StateObject.DEVICE;
            posStatus = (PosStatus)StateObject.POS;
        }

        /// <summary>
        /// 체크인 고객리스트 수신 
        /// </summary>
        /// <param name="phoneList">고객리스트(JSON)</param>
        /// <returns>체크인된고객수</returns>
        /// <remarks>
        /// * Connect List (JSON Format)
        /// 1	    DATETIME	YYYYMMDDHHMMSS	결과수신시간/처리시간
        /// 2	    POSID	    string	        요청POS 식별번호
        /// 3	    LIST	    JSONList	    체크인 고객리스트
        /// 3.1	    XPT	        String	        단말기 식별코드 (반복)
        /// 3.2	    NAME	    String	        단말기 등록이름 (반복)
        /// 3.3	    NICKNAME	String	        단말기 등록 닉네임 (반복)
        /// 3.4	    MDN	        String	        단말기 전화번호 (반복)
        /// 3.5	    DEVICE_TYPE	String	        “001” : 안드로이드, “002” : 아이폰(iOS 적용 버전)
        /// 
        /// * Sample 
        /// {
        ///     "DATETIME":"20160329144522",
        ///     "POSID":"WHONEED010",
        ///     "LIST":[
        ///             {"XPT":"********lVGOW48naN0mRPg==", "NAME":"**호", "NICK_NAME":"별명", "MDN":"01089**23**","DEVICE_TYPE":"001"}
        ///             …(반복)
        ///            ]
        /// }
        /// </remarks>
        public int GetConnectList(out string phoneList)
        {
            phoneList = string.Empty;
            try
            {
                byte[] buffer = new byte[1024 * 2];

                int ret = GetPOSConnectList(buffer);
                if (ret < 0)
                {
                    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 (함수명))
                                         "XPayLib.dll GetPOSConnectList Function Error (ErrorCode=" + ret.ToString() + ")"); 
                }
                phoneList = Encoding.Default.GetString(buffer).Replace("\0", "");

                return ret; 
            }
            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 (함수명))
                                     "Exception." + ex.Message);
                return -9;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="phoneList"></param>
        /// <returns></returns>
        public int GetConnectList(out Column.TPAY_CONNECT_INFO phoneList)
        {
            phoneList = null; 
            try
            {
                byte[] buffer = new byte[1024 * 2];

                int ret = GetPOSConnectList(buffer);
                string result = Encoding.Default.GetString(buffer).Replace("\0", "");
                if (ret < 0)
                {
                    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 (함수명))
                                         "XPayLib.dll GetPOSConnectList Function Error (ErrorCode=" + ret.ToString() + ")"); 
                    return ret; 
                }

                phoneList = new Column.TPAY_CONNECT_INFO();

                JObject json = JObject.Parse(result);
                phoneList.DATATIME = json["DATETIME"].ToString();
                phoneList.POSID = json["POSID"].ToString();

                JArray jArray = JArray.Parse(json["LIST"].ToString());
                for (var i = 0; i < ret; i++)
                {
                    JObject js = JObject.Parse(jArray[i].ToString());

                    Column.TPAY_PHONE phone = new Column.TPAY_PHONE();
                    phone.XPT = js["XPT"].ToString();
                    phone.NAME = js["NAME"].ToString();
                    phone.NICK_NAME = js["NICK_NAME"].ToString();
                    phone.MDN = js["MDN"].ToString();
                    phone.DEVICE_TYPE = js["DEVICE_TYPE"].ToString();

                    phoneList.LIST.Add(phone);
                }

                return ret;
            }
            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 (함수명))
                                     "Exception." + ex.Message);
                phoneList = null; 
                return -9;
            }
        }

        /// <summary>
        /// 선택된 XPT 단말기(스마트폰)에 BLE BOT 발급 요청
        /// </summary>
        /// <param name="xpt">결제키 발급대상 단말기 식별코드</param>
        /// <param name="posID">요청POS식별번호</param>
        /// <param name="deviceType">장비구분(001:안드로이드, 002:iOS)</param>
        /// <returns</returns>
        public bool ReqPosProvide(string xpt, string posID, string deviceType, out string errMsg)
        {
            errMsg = string.Empty;

            try
            {
                //byte[] param1 = Encoding.Default.GetBytes(xpt);
                //byte[] param2 = Encoding.Default.GetBytes(posID);
                //int ret = ReqPOSProvide(param1);

                string temp = JObject.FromObject(new { XPT = xpt, DEVICE_TYPE = deviceType }).ToString();
                //string temp = "{" + string.Format("\"XPT\":\"{0}\",\"DEVICE_TYPE\":\"{1}\"", xpt, deviceType) + "}";
                byte[] param1 = Encoding.Default.GetBytes(xpt);
                byte[] param2 = Encoding.Default.GetBytes(temp);
                int ret = ReqPOSProvide2(param1, param2);
                if (ret < 0)
                {
                    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 (함수명))
                                         "XPayLib.dll ReqPOSProvide2 Function Error (ErrorCode=" + ret.ToString() + ")"); 

                }

                errMsg = ret == 0 ? string.Empty : "Error Code =" + ret.ToString();
                return ret == 0 ? true : false; 
            }
            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 (함수명))
                                     "Exception." + ex.Message);
                errMsg = ex.Message;
                return false; 
            }
        }

        /// <summary>
        /// BLE OTB 수신
        /// </summary>
        /// <param name="result">성공:OTB, 실패:오류메시지</param>
        /// <returns></returns>
        /// <remarks>0:성공, -10001:Timeout, -10002:DeviceError</remarks>
        public bool GetOTB(out string result)
        {
            result = string.Empty;
            try
            {
                byte[] buffer = new byte[1024];
                int ret = GetOTB(buffer);
                switch(ret)
                {
                    case 0:
                        result = Encoding.Default.GetString(buffer).Replace("\0", "").Trim();
                        break;
                    case -10001:
                        result = "Timeout";
                        break;
                    case -10002:
                        result = "Device Error";
                        break;
                }
                if (ret != 0)
                {
                    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 (함수명))
                                         "XPayLib.dll GetOTB Function Error (ErrorCode=" + ret.ToString() + ", " + result + ")");
                }

                return ret == 0 ? true : false; 
            }
            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 (함수명))
                                     "Exception." + ex.Message);
                result = ex.Message;
                return false;
            }
        }

        /// <summary>
        /// 수신된 비밀번호를 40Byte 해시코드로 변환
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public string GetHashPassword(string password)
        {
            try
            {
                byte[] buffer = new byte[40];
                byte[] pws = new byte[4];
                pws = Encoding.Default.GetBytes(password);

                PWHashing(buffer, pws);

                return Encoding.Default.GetString(buffer).Replace("\0", "");
            }
            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 (함수명))
                                     "Exception." + ex.Message);
                return string.Empty;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CheckPaygle()
        {
            try
            {
                int ret = PaygleCheckProc();
                return ret == 0 ? true : false;
            }
            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 (함수명))
                                     "Exception." + ex.Message);
                return false; 
            }
        }


        //#20170906 T페이 고도화 작업 phj, start
        #region ## ClassifyOTBCheck 입력된 OTB의 유효성과, 선인증여부를 확인
        public int ClassifyOTBCheck(string pOTB)
        {
            int ret = 0;

            try
            {
                byte[] GetOTB = Encoding.Default.GetBytes(pOTB);

                //입력된 OTB의 유효성과, 선인증여부를 확인
                //10 : 구버전의 OTB로 제약 없음
                //20 : 할인/결제 가능, 핀패드 입력 필요
                //21 : 할인/결제 가능, 핀패드 입력 불필요
                //30 : 결제만 가능, 핀패드 입력 필요
                //31 : 결제만 가능, 핀패드 입력 불필요

                ret = ClassifyOTB(GetOTB);

                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 (함수명))
                                     "XPayLib.dll ClassifyOTB Function Result : " + ret.ToString() + ", (" + pOTB + ")");
                return ret;
            }
            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 (함수명))
                                     "XPayLib.dll ClassifyOTB Function Exception : " + ex.Message + ", Result : " + ret.ToString() + ", (" + pOTB + ")");
                return ret;
            }
        }

        #endregion
        //#20170906 T페이 고도화 작업 phj, end

        //#20170906 T페이 고도화 작업 phj, start
        #region ## ClassifyOTBCheckMsg 메세지 
        public string ClassifyOTBCheckMsg(string pOTB)
        {
            string result = string.Empty;
            try
            {
                switch (pOTB)
                {
                    case "0":
                        result = MessageManager.GetErrorMessage(POS_MESSAGE.ERROR.MSG_0729);//"유효하지 않은 OTB 입니다"
                        break;
                    case "10":
                        result = MessageManager.GetErrorMessage(POS_MESSAGE.ERROR.MSG_0730);//"구버전의 OTB 입니다"
                        break;
                    case "20":
                        result = MessageManager.GetErrorMessage(POS_MESSAGE.ERROR.MSG_0731);//"통합결제만 가능 합니다(결제비밀번호 필수)";
                        break;
                    case "21":
                        result = MessageManager.GetErrorMessage(POS_MESSAGE.ERROR.MSG_0732);//"통합결제만 가능 합니다(결제비밀번호 불필요)";
                        break;
                    case "30":
                        result = MessageManager.GetErrorMessage(POS_MESSAGE.ERROR.MSG_0733);//"일반결제만 가능 합니다(결제비밀번호 필수)";
                        break;
                    case "31":
                        result = MessageManager.GetErrorMessage(POS_MESSAGE.ERROR.MSG_0734);//"일반결제만 가능 합니다(결제비밀번호 불필요)";
                        break;

                    default:
                        result = MessageManager.GetErrorMessage(POS_MESSAGE.ERROR.MSG_0735);//"해당응답코드없음";
                        break;
                }
                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 (함수명))
                                     "XPayLib.dll ClassifyOTB Function Msg : " + result + ", (" + pOTB + ")");

                return result;

            }
            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 (함수명))
                                     "XPayLib.dll ClassifyOTB Function Msg Exception : " + ex.Message + ", Result : " + result + ", (" + pOTB + ")");
                return result;
            }
        }
        #endregion
        //#20170906 T페이 고도화 작업 phj, end
    }
}
