/******************************************************************************
 * 文件名称: CardReader.cs
 * 文件说明: 读卡的封装,包括社保卡,身份证,电子凭证等等
 * 当前版本: V1.0
 * 创建日期: 2022-06-20
 *
 * * 2020-06-20: 增加 CardReader 类
 * *****  2020-06-20: 增加 CardReader 方法,获取URL地址,USER信息,地方版SSCard.dll使用
 * *****  2020-06-20: 增加 CardReader 方法重载,国家版电子凭证使用
 * *****  2020-06-20: 增加 Init 方法,SSCard环境初始化
 * *****  2020-06-20: 增加 ReadCardBas 方法,读社保卡
 * *****  2020-06-20: 增加 VerifyPIN 方法,验证密码
 * *****  2020-06-20: 增加 ChangePIN 方法,修改密码
 * *****  2020-06-20: 增加 ReadSFZ 方法,读身份证
 * *****  2020-06-20: 增加 GetQRBase 方法,读二维码
 * *****  2020-06-20: 增加 NationEcTrans 方法,读电子凭证(国家版)


******************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using PTMedicalInsurance.Variables;
using System.Windows.Forms;
using PTMedicalInsurance.Helper;
using Newtonsoft.Json.Linq;

namespace PTMedicalInsurance.Common
{
    /// <summary>
    /// 通用读卡动态库调用
    /// </summary>
    class CardReader
    {
        const string DllPath = @"D:\CardDLL\SSCard.dll";

        [DllImport("SSCard.dll", EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int Init(StringBuilder pURL, StringBuilder pUser);

        [DllImport("SSCard.dll", EntryPoint = "ReadCardBas", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ReadCardBas(StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);

        [DllImport("SSCard.dll", EntryPoint = "VerifyPIN", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int VerifyPIN(StringBuilder pOutBuff, int nOutBuffLen);

        [DllImport("SSCard.dll", EntryPoint = "ChangePIN", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ChangePIN(StringBuilder pOutBuff, int nOutBuffLen);

        [DllImport("SSCard.dll", EntryPoint = "ReadSFZ", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ReadSFZ(StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);

        [DllImport("SSCard.dll", EntryPoint = "GetQRBase", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int GetQRBase(int nTimeout, StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);

        //电子凭证
        [DllImport("NationECCode.dll", EntryPoint = "NationEcTrans", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr NationEcTrans(StringBuilder strUrl, StringBuilder InData, StringBuilder OutData);

        private string URL;
        private string User;
        public CardReader()
        {

        }
        public CardReader(string URL, string User)
        {
            this.URL = URL;
            this.User = User;
        }

        public int Init()
        {
            string errMsg = "";
            int result = -1;
            try
            {
                StringBuilder sbURL = new StringBuilder(URL);
                StringBuilder sbUSER = new StringBuilder(User);

                result = Init(sbURL, sbUSER);
                return result;
            }
            catch (Exception ex)
            {
                errMsg = ex.Message;
                return result;

            }
            finally
            {
                Global.writeLog("初始化", URL + ":" + User, result.ToString() + ":" + errMsg);
            }
        }

        public int ReadCardBas(out string basInfo, out string regInfo)
        {
            basInfo = ""; regInfo = "";
            int rtn = -1;
            try
            {
                StringBuilder sbBasInfo = new StringBuilder(1024);
                StringBuilder sbRegInfo = new StringBuilder(1024);

                rtn = ReadCardBas(sbBasInfo, 1024, sbRegInfo, 1024);
                basInfo = sbBasInfo.ToString();
                regInfo = sbRegInfo.ToString();
                return rtn;
            }
            catch (Exception ex)
            {
                basInfo = "ReadCardBas异常:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("读社保卡(" + URL + ")", regInfo, basInfo);
            }
        }

        public int VerifyPIN(out string outBuff)
        {
            outBuff = "";
            int rtn = -1;
            try
            {
                StringBuilder sbOutBuff = new StringBuilder(1024);
                rtn = VerifyPIN(sbOutBuff, 1024);
                outBuff = sbOutBuff.ToString();
                return rtn;
            }
            catch (Exception ex)
            {
                outBuff = "VerifyPIN:" + ex.Message;
                return rtn;
            }
        }

        public int ChangePIN(out string outBuff)
        {
            outBuff = "";
            int rtn = -1;
            try
            {
                StringBuilder sbOutBuff = new StringBuilder(1024);
                rtn = ChangePIN(sbOutBuff, 1024);
                outBuff = sbOutBuff.ToString();
                return rtn;
            }
            catch (Exception ex)
            {
                outBuff = "ChangePIN:" + ex.Message;
                return rtn;
            }
        }

        public int ReadSFZ(out string OutBuff, out string SignBuff)
        {
            OutBuff = ""; SignBuff = "";
            int rtn = -1;
            try
            {
                StringBuilder sbOutBuff = new StringBuilder(1024);
                StringBuilder sbSignBuff = new StringBuilder(1024);

                rtn = ReadSFZ(sbOutBuff, 1024, sbSignBuff, 1024);
                OutBuff = sbOutBuff.ToString();
                SignBuff = sbSignBuff.ToString();
                return rtn;
            }
            catch (Exception ex)
            {
                OutBuff = "ReadSFZ 异常:" + ex.Message;
                return rtn;
            }
        }

        public int GetQRBase(int timeout, out string OutBuff, out string SignBuff)
        {
            OutBuff = ""; SignBuff = "";
            int rtn = -1;
            try
            {
                StringBuilder sbOutBuff = new StringBuilder(1024);
                StringBuilder sbSignBuff = new StringBuilder(1024);

                rtn = GetQRBase(timeout, sbOutBuff, 1024, sbSignBuff, 1024);
                OutBuff = sbOutBuff.ToString();
                SignBuff = sbSignBuff.ToString();
                return rtn;
            }
            catch (Exception ex)
            {
                OutBuff = "GetQRBase 异常:" + ex.Message;
                return rtn;
            }
        }

        public string NationEcTrans(string URL, string InData, out string OutData)
        {
            OutData = "";
            try
            {
                StringBuilder sbURL = new StringBuilder(URL);
                StringBuilder sbInData = new StringBuilder(InData);
                StringBuilder sbOutData = new StringBuilder(1024);

                IntPtr pRtn = NationEcTrans(sbURL, sbInData, sbOutData);
                OutData = sbOutData.ToString();
                string rtn = Marshal.PtrToStringAnsi(pRtn);
                return rtn;
            }
            catch (Exception ex)
            {
                OutData = "NationEcTrans 异常:" + ex.Message;
                return "-1";
            }
            finally
            {
                Global.writeLog("电子凭证(" + URL + ")", InData, OutData);
            }
        }

    }

    /// <summary>
    /// 甘肃读卡动态库调用
    /// </summary>
    class CardReader_GS
    {
        const string DllPath = @"D:\CardDLL\SSCard.dll";

        [DllImport("SSCard.dll", EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int Init(StringBuilder pURL, StringBuilder pUser);

        [DllImport("SSCard.dll", EntryPoint = "ReadCardBas", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ReadCardBas(StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);

        [DllImport("SSCard.dll", EntryPoint = "VerifyYBPZPass", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int VerifyYBPZPass(StringBuilder pHospcode, StringBuilder pIdcard, StringBuilder pAdmdvs, StringBuilder pOutBuff, int nOutBuffLen);

        [DllImport("SSCard.dll", EntryPoint = "ChangeYBPZPass", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ChangeYBPZPass(StringBuilder pHospcode, StringBuilder pIdcard, StringBuilder pName, StringBuilder pAdmdvs, StringBuilder pOutBuff, int nOutBuffLen);

        //电子凭证
        [DllImport("NationECCode.dll", EntryPoint = "NationEcTrans", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr NationEcTrans(StringBuilder strUrl, StringBuilder InData, StringBuilder OutData);

        private string URL;
        private string User;
        public CardReader_GS()
        {

        }

        public CardReader_GS(string URL, string User)
        {
            this.URL = URL;
            this.User = User;
        }

        public int Init()
        {
            string errMsg = "";
            int result = -1;
            try
            {
                StringBuilder sbURL = new StringBuilder(URL);
                StringBuilder sbUSER = new StringBuilder(User);

                result = Init(sbURL, sbUSER);
                return result;
            }
            catch (Exception ex)
            {
                errMsg = ex.Message;
                return result;
            }
            finally
            {
                Global.writeLog("初始化", URL + ":" + User, result.ToString() + ":" + errMsg);
            }
        }

        public int ReadCardBas(out string basInfo, out string regInfo)
        {
            basInfo = ""; regInfo = "";
            int rtn = -1;
            try
            {
                StringBuilder sbBasInfo = new StringBuilder(1024);
                StringBuilder sbRegInfo = new StringBuilder(1024);

                rtn = ReadCardBas(sbBasInfo, 1024, sbRegInfo, 1024);
                basInfo = sbBasInfo.ToString();
                regInfo = sbRegInfo.ToString();
                return rtn;
            }
            catch (Exception ex)
            {
                basInfo = "ReadCardBas异常:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("读社保卡(" + URL + ")", regInfo, basInfo);
            }
        }

        public int VerifyPIN(out string outBuff)
        {
            outBuff = "";
            int rtn = -1;
            try
            {
                //MessageBox.Show("验密:" + Global.pat.mdtrtcertType + "|" + Global.inf.hospitalNO + "|" + Global.pat.certNO + "|" + Global.pat.insuplc_admdvs + "|" + Global.pat.name);

                StringBuilder sbHospCode = new StringBuilder(Global.inf.hospitalNO);
                StringBuilder sbIdCard = new StringBuilder(Global.pat.certNO);
                StringBuilder sbAdmdvs = new StringBuilder(Global.pat.insuplc_admdvs);
                StringBuilder sbName = new StringBuilder(Global.pat.name);

                StringBuilder sbOutBuff = new StringBuilder(2048);
                //rtn =
                rtn = VerifyYBPZPass(sbHospCode, sbIdCard, sbAdmdvs, sbOutBuff, 2048);

                outBuff = sbOutBuff.ToString();

                //Global.writeLog("验密返回:", rtn.ToString(), outBuff);
                //MessageBox.Show("验密返回:" + rtn.ToString() + "| sbOutBuff:" + sbOutBuff.ToString());

                //if (outBuff == "成功")
                //    rtn = 0;

                return rtn;
            }
            catch (Exception ex)
            {
                outBuff = "VerifyPIN:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("社保卡验密:", Global.inf.hospitalNO + "|" + Global.pat.certNO + "|" + Global.pat.insuplc_admdvs, rtn+"|"+outBuff);
            }
        }     

        public int ChangePIN(out string outBuff)
        {
            outBuff = "";
            int rtn = -1;
            try
            {
                Global.writeLog("社保卡密码更改:", Global.inf.hospitalNO + "|" + Global.pat.certNO + "|" + Global.pat.insuplc_admdvs + "|" + Global.pat.name, outBuff);

                StringBuilder sbHospCode = new StringBuilder(Global.inf.hospitalNO);
                StringBuilder sbIdCard = new StringBuilder(Global.pat.certNO);
                StringBuilder sbAdmdvs = new StringBuilder(Global.pat.insuplc_admdvs);
                StringBuilder sbName = new StringBuilder(Global.pat.name);
                StringBuilder sbOutBuff = new StringBuilder(1024);
                
                rtn = ChangeYBPZPass(sbHospCode, sbIdCard, sbName, sbAdmdvs, sbOutBuff, 1024);
                outBuff = sbOutBuff.ToString();
               
                return rtn;
            }
            catch (Exception ex)
            {
                outBuff = "ChangePIN:" + ex.Message;
                return rtn;
            }
        }

        public string NationEcTrans(string URL, string InData, out string OutData)
        {
            OutData = "";
            try
            {
                StringBuilder sbURL = new StringBuilder(URL);
                StringBuilder sbInData = new StringBuilder(InData);
                StringBuilder sbOutData = new StringBuilder(1024);

                IntPtr pRtn = NationEcTrans(sbURL, sbInData, sbOutData);
                OutData = sbOutData.ToString();
                string rtn = Marshal.PtrToStringAnsi(pRtn);
                return rtn;
            }
            catch (Exception ex)
            {
                OutData = "NationEcTrans 异常:" + ex.Message;
                return "-1";
            }
            finally
            {
                Global.writeLog("电子凭证(" + URL + ")", InData, OutData);
            }
        }

    }

    /// <summary>
    /// 黑龙江读卡动态库调用
    /// </summary>
    class CardReader_HLJ
    {
        string progID = "SCardDriverHLJ.SCard";
        System.Type ComType;
        object ComInstance;

        public CardReader_HLJ()
        {
            ComType = Type.GetTypeFromProgID(progID);
            // 创建Com的实例
            if (ComType != null)
            {
                //创建实例
                ComInstance = Activator.CreateInstance(ComType);
            }
        }

        public string readCardBas(int type, string hospNO)
        {
            if (ComType == null)
            {
                return "ComType为空!";
            }

            if (ComInstance == null)
            {
                return "ComInstance为空!";
            }
            try
            {
                //设置需要设置的参数值
                object[] ParamArray = new object[2];
                ParamArray[0] = type;
                ParamArray[1] = hospNO;
                ParameterModifier[] ParamMods = new ParameterModifier[1];
                ParamMods[0] = new ParameterModifier(2); // 初始化为接口参数的个数
                ParamMods[0][0] = true;
                ParamMods[0][1] = true; // 设置第二个参数为返回参数,调用含有ParameterModifier数组的重载函数

                object o = ComType.InvokeMember("iReadCardBas", // 接口函数名
                 BindingFlags.Default | BindingFlags.InvokeMethod,
                null,
                ComInstance, // 调用的COM组件
                ParamArray, // 参数数组
                ParamMods, // 指定返回参数的ParameterModifier数组
                null,
                null);

                //string Msg = "加载成功:" + ParamArray[1].ToString();
                //Global.inf.writeLog(Msg + "___" + ParamArray[0].ToString());
                return o.ToString();
            }
            catch (Exception ex)
            {
                return "异常:" + ex.Message;
            }
        }
    }

    /// <summary>
    /// 河南读卡动态库调用
    /// </summary>
    class CardReader_HN
    {
        //电子凭证
        [DllImport("NationECCode.dll", EntryPoint = "NationEcTrans", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr NationEcTrans(StringBuilder strUrl, StringBuilder InData, StringBuilder OutData);
        //社保卡-本地
        [DllImport("SSCardDriver.dll", EntryPoint = "iReadCardBas", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ReadCardBas(int iType, StringBuilder pDevInfo, StringBuilder pOutInfo);
        //社保卡-异地1
        [DllImport("SSCardDriver.dll", EntryPoint = "iReadCardBas_HSM_Step1", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ReadCardBas_HSM_Step1(int iType, StringBuilder pDevInfo, StringBuilder pOutInfo);
        //社保卡-异地2
        [DllImport("SSCardDriver.dll", EntryPoint = "iReadCardBas_HSM_Step2", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int ReadCardBas_HSM_Step2(StringBuilder pKey, StringBuilder pOutInfo);
        //社保卡-PIN校验
        [DllImport("SSCardDriver.dll", EntryPoint = "iVerifyPIN", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        static extern int VerifyPIN(int iType, StringBuilder pOutInfo);

        public int ReadCardBas(int iType, string sDevInfo, out string sOutInfo)
        {
            sOutInfo = ""; 
            int rtn = -1;
            try
            {
                StringBuilder bDevInfo = new StringBuilder(sDevInfo);                
                StringBuilder bOutInfo = new StringBuilder(1024);

                rtn = ReadCardBas(iType, bDevInfo, bOutInfo);
                sOutInfo = bOutInfo.ToString();
                
                return rtn;
            }
            catch (Exception ex)
            {
                sOutInfo = "ReadCardBas异常:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("调用社保卡ReadCardBas函数:",sDevInfo, sOutInfo);
            }
        }

        public int VerifyPIN(int iType, out string sOutInfo)
        {
            sOutInfo = "";
            int rtn = -1;
            try
            {
                StringBuilder bOutInfo = new StringBuilder(1024);

                rtn = VerifyPIN(iType, bOutInfo);
                sOutInfo = bOutInfo.ToString();

                return rtn;
            }
            catch (Exception ex)
            {
                sOutInfo = "iVerifyPIN异常:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("调用社保卡iVerifyPIN函数:", iType.ToString(), sOutInfo);
            }
        }

        public int ReadCardBas_HSM_Step1(int iType, string sDevInfo, out string sOutInfo)
        {
            sOutInfo = "";
            int rtn = -1;
            try
            {
                StringBuilder bDevInfo = new StringBuilder(sDevInfo);
                StringBuilder bOutInfo = new StringBuilder(1024);

                rtn = ReadCardBas_HSM_Step1(iType, bDevInfo, bOutInfo);
                sOutInfo = bOutInfo.ToString();

                return rtn;
            }
            catch (Exception ex)
            {
                sOutInfo = "ReadCardBas_HSM_Step1异常:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("调用社保卡ReadCardBas_HSM_Step1函数:", iType+"|"+ sDevInfo, sOutInfo);
            }
        }

        public int ReadCardBas_HSM_Step2(string pKey, out string sOutInfo)
        {
            sOutInfo = "";
            int rtn = -1;
            try
            {
                StringBuilder bPKey = new StringBuilder(pKey);
                StringBuilder bOutInfo = new StringBuilder(1024);

                rtn = ReadCardBas_HSM_Step2(bPKey, bOutInfo);
                sOutInfo = bOutInfo.ToString();

                return rtn;
            }
            catch (Exception ex)
            {
                sOutInfo = "ReadCardBas_HSM_Step2异常:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("调用社保卡ReadCardBas_HSM_Step2函数:", pKey, sOutInfo);
            }
        }

        public string NationEcTrans(string URL, string InData, out string OutData)
        {
            OutData = "";            
            try
            {              
                StringBuilder sbURL = new StringBuilder(URL);
                StringBuilder sbInData = new StringBuilder(InData);
                StringBuilder sbOutData = new StringBuilder(1024);

                IntPtr pRtn = NationEcTrans(sbURL, sbInData, sbOutData);
                OutData = sbOutData.ToString();

                //MessageBox.Show("电子凭证NationEcTrans返回的:" + pRtn);

                string rtn = Marshal.PtrToStringAnsi(pRtn);
                return rtn;
            }
            catch (Exception ex)
            {
                OutData = "NationEcTrans 异常:" + ex.Message;
                return "";
            }
            finally
            {
                Global.writeLog("电子凭证(" + URL + ")", InData, OutData);
            }
        }
    }

    #region【调用正版FastRepor打印】
    class FastReportPrint
    {
        //医保结算单打印调用正版FastReport
        [DllImport(@"C:\ProgramData\prykNT\prBrowser\bin\service\plugins\INSUNew\FastReportFrom.dll", EntryPoint = "Main", 
                   CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        public static extern string FastReport(StringBuilder InData);

        public int FastReport(string sInput, out string sOutInfo)
        {
            string errMsg;
            sOutInfo = "";
            int rtn = -1;
            try
            {
                StringBuilder bInput = new StringBuilder(sInput);
                
                sOutInfo = FastReport(bInput);
                JObject joRetObj = JObject.Parse(sOutInfo);

                if (JsonHelper.parseIrisRtnValue(joRetObj, out errMsg) != 0)
                {
                    errMsg = "调用FastReport打印失败!" + errMsg;
                    return rtn;
                }
                else
                {
                    return 0;
                }                
            }
            catch (Exception ex)
            {
                sOutInfo = "FastReportPrint异常:" + ex.Message;
                return rtn;
            }
            finally
            {
                Global.writeLog("调用FastReportPrint函数:", sInput, sOutInfo);
            }
        }
    }
    #endregion

}