#define VIEW_EMV_TRACE

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using YalkoEmvClassLibrary;
using System.IO;

namespace EmvLibWinDotNetExample_x86
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        YalkoEmvClass emv_lib = new YalkoEmvClass();
        EMVLibraryDelegate emv_delegate = new EMVLibraryDelegate();
       

        private void buttonEmvRun_Click(object sender, EventArgs e)
        {
            emv_lib.EmvRun(emv_delegate);
        }

        private void buttonViewTrace_Click(object sender, EventArgs e)
        {
#if VIEW_EMV_TRACE
            textBox1.Text = emv_delegate.GetTraceString();
#endif
        }

        private void buttonClearTrace_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
#if VIEW_EMV_TRACE
            emv_delegate.ClearTraceString();
#endif
        }

        public class EMVLibraryDelegate : YalkoEmvClass, YalkoEmvClass.EMVLibraryDelegate
        {
            bool get_tr_data_already_started = false;
#if VIEW_EMV_TRACE
            public string emv_trace_str = "";
            public string GetTraceString()
            {
                return emv_trace_str;
            }
            public void ClearTraceString()
            {
                emv_trace_str = "";
            }
#endif
            public string GetField_55(int lpHandle)
            {
                //Create field 55
                //ISO 8583 clearing a field P-55 containing chip data
                String sField_55 =
                        "9F26" //    
                        + "9F27" //    
                        + "9F10" //    
                        + "9F37" //    
                        + "9F36" //    
                        + "95"   //    
                        + "9A"   //    
                        + "9C"   //    
                        + "9F02" //    
                        + "5F2A" //    
                        + "82"   //    
                        + "9F1A" //    
                        + "9F03" //    
                        + "9F34" //    
                        + "9F33" //    
                        + "9F35" //    
                        + "9F1E" //    
                        + "9F53" //    
                        + "84"   //    
                        + "9F09" //    
                        + "9F41"; //   
                String answer = GetTLVBufByDOL(lpHandle, sField_55);
#if VIEW_FIELD55_BY_MESSAGE_BOX
                MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                MessageBox.Show(answer, "Field 55:", buttons);
#endif
                return answer;
            }

            public void fEmvTrace(int lpHandle, String s)
            {
#if VIEW_EMV_TRACE
            emv_trace_str += s;
#endif
            }
            public void fEmvEnd_Delegate(int lpHandle)
            {

            }
            public void fAppSelected()
            {
            }
            public unsafe byte fAtr_Delegate(int lpHandle, ref String atr, byte* protocol)
            {
                atr = "3B620000811F";
                *protocol = 0;//0 => T0, 1 => T1
                return 1;//ok
            }

            String CardSimulator(String sCmd, String sData)
            {
                if (sData.Length > 0)//&& apdu_data_len < sizeof(sData)/2)
                {
                    if (sCmd.Equals("00A404000E") && sData.Equals("315041592E5359532E4444463031"))
                    {
                        return "6A82";
                    }
                    else
                        if (sCmd.Equals("00A4040007") && sData.Equals("A0000000031010"))
                        {
                            return "6F318407A0000000031010A526500B56495341204352454449549F120F4352454449544F20444520564953418701019F1101019000";
                        }
                        else
                            if (sCmd.Equals("00A4040007") && sData.Equals("A0000000041010"))
                            {
                                return "6F318407A0000000041010A526500B4D415354455220434152449F120F4452454449544F20444520564953418701019F1101019000";
                            }
                            else

                                if (sCmd.Equals("80A8000002") && sData.Equals("8300"))
                                {
                                    return "800E5C000801010010010300180102019000";
                                }
                                else
                                    if (sCmd.Equals("80AE80001D"))// && sData.Equals("00000001000000000000000008404000048000064313083100E9C4B090"))
                                    {
                                        return "80128000018B5911CDEBC190F506010A039000009000";
                                    }
                                    else
                                        if (sCmd.Equals("008200000A"))// && sData.Equals("993680ED37FC09533030"))
                                        {
                                            return "9000";
                                        }
                                        else
                                            if (sCmd.Equals("80AE40001F"))// && sData.Equals("3030000000010000000000000000084040000480000643130831006D4B0149"))
                                            {
                                                return "8012400001492136F956F8B83006010A036000009000";
                                            }
                                            else
                                                if (sCmd.Equals("80AE00001F"))// && sData.Equals("3030000000010000000000000000084040000480000643130831006D4B0149"))
                                                {
                                                    return "8012000001492136F956F8B83006010A036000009000";
                                                }
                                                else
                                                    if (sCmd.Substring(0, 8).Equals("00A404000"))
                                                    {
                                                        return "6A82";
                                                    }
                                                    else
                                                    {
                                                        //Log.i("Emv", "CardSimulator ERROR! No Equals for command = " + sCmd +" data = " + sData);
                                                    }

                }
                else
                {
                    if (sCmd.Equals("00B2010C00"))
                    {
                        return "70435F201A564953412041435155495245522054455354204341524420303157114761739001010010D101220111438780899F1F10313134333830303738303030303030309000";
                    }
                    else
                        if (sCmd.Equals("00B2011400"))
                        {
                            return "7081939081908B3901F6253048A8B2CB08974A4245D90E1F0C4A2A69BCA469615A71DB21EE7B3AA94200CFAEDCD6F0A7D9AD0BF79213B6A418D7A49D234E5C9715C9140D87940F2E04D6971F4A204C927A455D4F8FC0D6402A79A1CE05AA3A526867329853F5AC2FEB3C6F59FF6C453A7245E39D73451461725795ED73097099963B82EBF7203C1F78A529140C182DBBE6B42AE00C029000";
                        }
                        else
                            if (sCmd.Equals("00B2021400"))
                            {
                                return "702D8F01959F320103922433F5E4447D4A32E5936E5A1339329BB4E8DD8BF0044CE4428E24D0866FAEFD2348809D719000";
                            }
                            else
                                if (sCmd.Equals("00B2031400"))
                                {
                                    return "708193938190919D6C210B3981D1C99B3AD55EDF36A138FFAD54D838FA40622AB97046E05EA6E6230AB89D5BE871114EB5431B97403B8C3D2D4CA9BB625AC13FD8C6B825433656CB56557AAC396D945F6D4014FB6E71E8DBEA74B285E9CF3FCEABDFA61D5A4BE16DAAA433F7F2644B178A7DD93DA98BB9D10E84298BDB6B6AE02D04E6E5558C77E79F82C9E046DF821DD0277AB9D00C9000";
                                }
                                else
                                    if (sCmd.Equals("00B2011C00"))
                                    {
                                        return "700E5A0847617390010100105F3401019000";
                                    }
                                    else
                                        if (sCmd.Equals("00B2021C00"))
                                        {
                                            return "707D9F420208405F25039507015F24031012319F0802008C5F280208405F300202019F0702FF008E0E00000000000000001E0302031F008C159F02069F03069F1A0295055F2A029A039C019F37048D178A029F02069F03069F1A0295055F2A029A039C019F37049F0D05F0400088009F0E0500100000009F0F05F0400098009000";
                                        }
                                        else
                                        {
                                            //Log.i("Emv", "CardSimulator ERROR! No Equals for command = " + sCmd);
                                        }
                }
                return "";
            }

            public string fApdu_Delegate(int lpHandle, string sApdu)
            {
                if (sApdu.Length > 9)
                {
                    if (sApdu.Length > 10)
                    {
                        String sApdu_cmd = sApdu.Substring(0, 10);
                        String sApdu_data = sApdu.Substring(10, sApdu.Length - 10);
                        String str = CardSimulator(sApdu_cmd, sApdu_data);

                        //MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                        //MessageBox.Show("cmd = " + sApdu_cmd + "\r\ndata = " + sApdu_data + "\r\nanswer =\r\n" + str, "", buttons);
                        return str;
                    }
                    else
                    {
                        String sApdu_cmd = sApdu.Substring(0, 10);
                        String str = CardSimulator(sApdu_cmd, "");

                        //MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                        //MessageBox.Show("cmd = " + sApdu_cmd + "\r\nanswer =\r\n" + str, "", buttons);
                        return str;
                    }
                }
                else
                {
                    MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                    MessageBox.Show("return null", "APDU ERROR!", buttons);
                    return null;
                }
            }
            public unsafe byte fHostSwop_Delegate(int lpHandle,
                     string data_after_GAC1,
                     ref string host_answer,
                     ref string host_answer71,
                     ref string host_answer72
                    )
            {
                String field_55 = GetField_55(lpHandle);

                host_answer = "910A963680ED37FC095330308A023030";
                host_answer71 = "710F860D8424000008EDBB6BE453CA32C48A023030";
                host_answer72 = "720F860D8424000008EDBB6BE453CA32C48A023030";
                return 0;//ok
            }
            public unsafe byte fGetTrData_Delegate(int lpHandle,
                    ref string amount_max_6_bytes,
                    ref string amount_other_max_6_bytes,
                    ref string currency_max_2_bytes,
                    ref string operation_type_1_byte,
                    ref string pin_entry_statys_1_byte
                    )
            {
                amount_max_6_bytes = "10000";//100,00
                amount_other_max_6_bytes = "1000";//10,00
                currency_max_2_bytes = "840";//USD
                operation_type_1_byte = "00";//PURCHES
                pin_entry_statys_1_byte = "00";//OK
                return 0;//ok
            }

            public unsafe byte fGetPin_Delegate(int lpHandle, byte FlagTryAgain, ref String pin_data, byte min, byte max)
            {
                //#define GET_PIN_OK              0
                //#define GET_PIN_ABORT           1
                //#define GET_PIN_TIMEOUT         2
                //#define GET_PIN_LIMIT_EXCEEDED  3
                pin_data = "1234";
                return 0;//GET_PIN_OK 
            }
            public byte fGetCryptPin_Delegate(int lpHandle, ref String pin_data)
            {
                //#define GET_PIN_OK              0
                //#define GET_PIN_ABORT           1
                return 0;//GET_PIN_OK 
            }
            public byte fSelLang_Delegate(int lpHandle, ref String lang)
            {
                lang = "EN"; 
                return 1;//ok //English
            }
            public byte fSelectAccount_Delegate(int lpHandle)
            {
                byte RC = 0x10;
                switch (RC)
                {
                    case 1: return 0x10;// 0     => Savings     
                    case 2: return 0x20;// 2     => Cheque/debit
                    case 3: return 0x30;// 3     => Credit      
                    case 4: return 0x00;// 4     => Default – no account specified.
                    default:
                        break;
                }
                return 0xFF;//err
            }
            public byte fSelApp_Delegate(int lpHandle, byte flagRetry, byte[] code_table, string[] AppList, string[] AidList)
            {
                MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                DialogResult result;

                if (flagRetry != 0)
                {
                    result = MessageBox.Show("Please Select Again", "Please Select Again", buttons);

                    if (result != DialogResult.Yes)
                    {
                        return 0;
                    }
                }

#if SELECT_APP_BY_MESSAGE_BOX 
            for (int i = 0; i < AppList.Length; i++)
            {

                result = MessageBox.Show(

                    "Application(" + (i + 1) + ") = " + AppList[i]
                    + "\r\n(AID = " + AidList[i] + " Code Table = " + code_table[i] + ")"

                    , "Please select Application",
                    buttons);

                if (result == DialogResult.Yes)
                {
                    return (byte)(i + 1);//1 => first application selected
                }
            }
            return 0;// error
#else
                return 1;// => selected first application
#endif
            }
        }

        void EmvInitTerminalParam()
        {
            string currentDirectory = Directory.GetCurrentDirectory();
            string dir_path = currentDirectory + "\\EmvParams\\";
            string fpath = dir_path
                     + "TrParam.txt";
            try
            {
                if (Directory.Exists(dir_path))
                {
                    try
                    {
                        using (StreamReader sr = new StreamReader(fpath))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                if (emv_lib.EmvInitTerminalParam(line) == 0)//ok
                                {
                                    //other_functions.ViewTrace("Ok: " + line);
                                }
                                else
                                {
                                    //other_functions.ViewTrace("Err: " + line);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //other_functions.ViewTrace("The file could not be read:");
                        //other_functions.ViewTrace(e.Message);
                    }
                }
                else
                {
                    //other_functions.ViewTrace("The folder is not exist : " + dir_path);
                    //other_functions.ViewTrace("Can't create file : " + fpath);
                }
            }
            catch (System.Exception ex)
            {
                //other_functions.ViewTrace("Can not to create file : " + fpath + " Exception=" + ex.ToString());
                //other_functions.ViewTrace("Can not to create file : " + fpath + " Exception=" + ex.ToString());
            }
        }
        void EmvInitPublicKeys()
        {
            string currentDirectory = Directory.GetCurrentDirectory();
            string dir_path = currentDirectory + "\\EmvParams\\";
            string fpath = dir_path
                     + "PublicKeys.txt";

            //other_functions.ViewTrace("read file : " + fpath);

            try
            {
                if (Directory.Exists(dir_path))
                {
                    try
                    {
                        using (StreamReader sr = new StreamReader(fpath))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                if (emv_lib.EmvInitTerminalParam(line) == 0)
                                {
                                    //other_functions.ViewTrace("Ok: " + line);
                                }
                                else
                                {
                                    //other_functions.ViewTrace("Err: " + line);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //other_functions.ViewTrace("The file could not be read:");
                        //other_functions.ViewTrace(e.Message);
                    }
                }
                else
                {
                    //other_functions.ViewTrace("The folder is not exist : " + dir_path);
                    //other_functions.ViewTrace("Can't create file : " + fpath);
                }
            }
            catch (System.Exception ex)
            {
                //other_functions.ViewTrace("Can not to create file : " + fpath + " Exception=" + ex.ToString());
                //other_functions.ViewTrace("Can not to create file : " + fpath + " Exception=" + ex.ToString());
            }
        }
        void EmvInitRevocationList()
        {
            string currentDirectory = Directory.GetCurrentDirectory();
            string dir_path = currentDirectory + "\\EmvParams\\";
            string fpath = dir_path
                     + "RevocationList.txt";

            //other_functions.ViewTrace("read file : " + fpath);

            try
            {
                if (Directory.Exists(dir_path))
                {
                    try
                    {
                        using (StreamReader sr = new StreamReader(fpath))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                if (emv_lib.EmvInitTerminalParam(line) == 0)//ok
                                {
                                    //other_functions.ViewTrace("Ok: " + line);
                                }
                                else
                                {
                                    //other_functions.ViewTrace("Err: " + line);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //other_functions.ViewTrace("The file could not be read:");
                        //other_functions.ViewTrace(e.Message);
                        MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                        MessageBox.Show("The file could not be read:" + e.Message, "EmvInitRevocationList()", buttons);
                    }
                }
                else
                {
                    //other_functions.ViewTrace("The folder is not exist : " + dir_path);
                    //other_functions.ViewTrace("Can't create file : " + fpath);
                    MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                    MessageBox.Show("The folder is not exist : " + dir_path + " Can't create file : " + fpath, "EmvInitRevocationList()", buttons);
                }
            }
            catch (System.Exception ex)
            {
                //other_functions.ViewTrace("Can not to create file : " + fpath + " Exception=" + ex.ToString());
                //other_functions.ViewTrace("Can not to create file : " + fpath + " Exception=" + ex.ToString());
                MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                MessageBox.Show("Can not to create file : " + fpath + " Exception=" + ex.ToString(), "EmvInitRevocationList()", buttons);

            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            emv_lib.EmvClearTerminalParam();
            EmvInitTerminalParam();

            emv_lib.EmvClearPublicKeys();
            EmvInitPublicKeys();

            emv_lib.EmvClearRevocationList();
            EmvInitRevocationList();
        }
    }
}
