#include <stdio.h>
#include <string.h>
#include <time.h>
#include "demo_common.h"

extern IDT_COMMON_PROCESS COMMON;
extern IDT_PROCESS idtech_process;
extern IDT_DEMO_LIB_DISPLAY_MENU idtech_display_menu_from_lib;

void
_VP3300_display_device_menu();

void
WorldPayCallback(char * message, int returnCode, int emvCode) {
    printf("WORLDPAY RESPONSE>>>>>>>\n");
    printf("Return Code = %d\n", returnCode);
    printf("EMV Code = %d\n", emvCode);
    printf("Message = \n%s\n", message);
    //	 _VP3300_AJ_display_device_menu();
    if (idtech_display_menu_from_lib.pDisplay_Menu_current) {
        idtech_display_menu_from_lib.pDisplay_Menu_current();
        printf("Please Input your Selection. (0 - exit current menu)\n");
    }
}

void
_VP3300_process_device() {
    int choice;
    int r = 0;
    char str1[256] = { 0 };
    int len        = 512;
//    int counter = 5;

    memset(str1, 0, 256);
    emv_setAutoAuthenticateTransaction(1);
    emv_setAutoCompleteTransaction(1);
    do {
        _VP3300_display_device_menu();
        choice = COMMON.inputSelection();
        switch (choice) {
            case 1:
                printf(">>1. Start Transaction\n");
                fflush(stdout);
                r = device_startTransaction(1.00, 0.00, 0, 30, NULL, 0);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS && r != IDG_P2_STATUS_CODE_REQUEST_ONLINE_AUTHORIZATION &&
                  r != IDG_P2_STATUS_CODE_OK_AND_HAVE_NEXT_COMMAND) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Start Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Start Transaction Succeeded\n");
                    if (r == IDG_P2_STATUS_CODE_OK_AND_HAVE_NEXT_COMMAND) {
                        printf("Please Use Card...\n");
                        //					isDeviceTransaction = 1;
                    }
                }
                fflush(stdout);
                break;
            case 2:
                printf(">>2. Cancel Transaction\n");
                fflush(stdout);
                r = device_cancelTransaction();
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    printf("  Do device_cancelTransaction(), failed!\n");
                } else {
                    printf("Cancel Transaction successfully\n");
                }
                fflush(stdout);
                break;
            case 3: {
                printf(">>3. Get Transaction Results\n");
                fflush(stdout);
                IDTMSRData cardData;
                resetMSRData(&cardData);
                r = device_getTransactionResults(&cardData);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Transaction Result Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    COMMON.printMSRData(&cardData);
                }
                fflush(stdout);
            }
            break;
            case 4: {
                printf(">>4. Get Firmware Version\n");
                fflush(stdout);
                r = device_getFirmwareVersion(str1);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Firmware Version Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    char str2[200] = { 0 };
                    sprintf(str2, "Firmware version: %s\n", str1);
                    printf(str2);
                }
                fflush(stdout);
            }
            break;
            case 5: {
                printf(">>5. Send Command: 0x29, 0x00\n");
                fflush(stdout);
                BYTE rbbyte[512] = { 0 };
                memset(rbbyte, 0, 512);
                len = 512;
                r = device_SendDataCommandNEO(0x29, 0x00, NULL, 0, rbbyte, &len); // default
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_SendDataCommand(), failed! ErrorCode:0x%02x ,Info: %s ----- \n", r,
                        strErr);
                } else {
                    char str3[1024] = { 0 };
                    memset(str3, 0, 1024);
                    COMMON.convertBytesIntoHexStr(rbbyte, len, 0, str3);
                    printf("response code : %s\n", str3);
                }
                fflush(stdout);
            }
            break;
            case 6: {
                printf(">>6. Get Serial Number\n");
                fflush(stdout);
                r = config_getSerialNumber(str1);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Serial Number Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    char str2[200] = { 0 };
                    sprintf(str2, "Serial Number: %s\n", str1);
                    printf(str2);
                }
                fflush(stdout);
            }
            break;
            case 7: {
                printf(">>7. Ping Device\n");
                fflush(stdout);
                r = device_pingDevice();
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Ping Device Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Ping Device Succeeded\n");
                }
                fflush(stdout);
            }
            break;
            case 8:
                printf(">>8. Interface Control\n");
                fflush(stdout);
                BYTE values[4] = { 0xFF, 0x04, 0xFF, 0x01 };
                r = device_controlUserInterface(values);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Interface Control Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Interface Control Succeeded\n");
                }
                fflush(stdout);
                break;
            case 9:
                printf(">>9. Pass Through On\n");
                fflush(stdout);
                r = device_enablePassThrough(1);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Pass Through On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Pass Through On Succeeded\n");
                }
                fflush(stdout);
                break;
            case 10:
                printf(">>10. Pass Through Off\n");
                fflush(stdout);
                r = device_enablePassThrough(0);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Pass Through Off Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Pass Through Off Succeeded\n");
                }
                fflush(stdout);
                break;
            case 11:
                printf(">>11. Set Burst On\n");
                fflush(stdout);
                r = device_setBurstMode(1);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Burst Mode On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Set Burst On Succeeded\n");
                }
                fflush(stdout);
                break;
            case 12:
                printf(">>12. Set Burst Off\n");
                fflush(stdout);
                r = device_setBurstMode(0);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Burst Mode Off Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Set Burst Off Succeeded\n");
                }
                fflush(stdout);
                break;

            case 13:
                printf(">>13. Set Auto Poll On\n");
                fflush(stdout);
                r = device_setPollMode(0);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Auto Poll On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Set Auto Poll On Succeeded\n");
                }
                fflush(stdout);
                break;
            case 14:
                printf(">>14. Poll On Demand\n");
                fflush(stdout);
                r = device_setPollMode(1);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Poll On Demand Failed! ErrorCode:0x%02x, Info: %s ----- \n",
                        r, strErr);
                } else {
                    printf("Set Poll On Demand Succeeded\n");
                }
                fflush(stdout);
                break;
            case 15:
                printf(">>15. Set Merchant Record\n");
                fflush(stdout);
                r = device_setMerchantRecord(1, 1, "pass.com.firstdata.money2020", null);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Merchant Record Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Set Merchant Record Succeeded\n");
                }
                fflush(stdout);
                break;
            case 16:
                printf(">>16. Get Merchant Record\n");
                fflush(stdout);
                BYTE record[0x63];
                memset(record, 0, 0x63);
                r = device_getMerchantRecord(1, record);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Merchant Record Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Get Merchant Record Succeeded\n");
                    int i;
                    printf("Record:\n");
                    for (i = 0; i < 0x63; i++) {
                        printf("%02X", record[i]);
                    }
                    printf("\n");
                }
                fflush(stdout);
                break;
            case 17: {
                printf(">>17. Set Date Time\n");
                fflush(stdout);
                BYTE dateTime[] = { 0x17, 0x10, 0x25, 0x12, 0x25, 0x10 };
                r = device_setRTCDateTime(dateTime, 6);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Date Time Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Set Date Time Succeeded\n");
                }
                fflush(stdout);
            }
            break;
            case 18: {
                printf(">>18. Get Date Time\n");
                fflush(stdout);
                BYTE dateTime[6] = { 0 };
                int dateTimeLen  = 6;
                r = device_getRTCDateTime(dateTime, &dateTimeLen);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Date Time Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Get Date Time Succeeded\n");
                    printf("%02X/%02X/%02X %02X:%02X:%02X\n", dateTime[0], dateTime[1], dateTime[2], dateTime[3],
                      dateTime[4], dateTime[5], dateTime[6]);
                }
                fflush(stdout);
            }
            break;
            case 19: {
                printf(">>19. Start Remote Key Injection\n");
                char option[10] = { 0 };
                while (option[0] != '0' && option[0] != '1') {
                    printf("Please enter 0 for Demo unit or 1 for Production unit:\n");
                    fflush(stdout);
                    fgets(option, 10, stdin);
                }
                int opt = 0;
                if (option[0] == '1') {
                    opt = 1;
                }
                r = device_startRKI(NULL, opt);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Remote Key Injection Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Start Remote Key Injection, please wait...\n");
                }
                fflush(stdout);
            }
            break;
            case 20:
                printf(">>20. WorldPay Sale Transaction\n");

                WorldPayData data_1;
                strcpy(data_1.accountID, "1188346\0");
                strcpy(data_1.accountToken, "E1EB3EFB049DFB599F1CB454E1CFC4FD14BF90BCE74456AE9E9490D7D609B466C81A3801\0");
                strcpy(data_1.acceptorID, "364798674\0");
                data_1.transactionType = TRANSACTION_TYPE_SALE;
                // data_1.transactionType = TRANSACTION_TYPE_PRE_AUTH;
                // data_1.transactionType = TRANSACTION_TYPE_COMPLETION;
                // data_1.transactionType = TRANSACTION_TYPE_VOID;
                // data_1.transactionType = TRANSACTION_TYPE_RETURN;
                // data_1.transactionType = TRANSACTION_TYPE_CREDIT;
                // data_1.transactionType = TRANSACTION_TYPE_QUICK_CHIP_START;
                // data_1.transactionType = TRANSACTION_TYPE_QUICK_CHIP_FINISH;
                strcpy(data_1.amount, "22.00\0");                 // specify transaction Amount
                data_1.timeout = 30;                              // Timeout for transaction
                data_1.isTest  = 1;                               // if test transaction, set to TRUE.  If live transactions, set to FALSE
                data_1.msrOnly = 0;                               // for EMV + MSR, set to FALSE.  If MSR swipe only, set to TRUE
                data_1.enableCTLS = 1;                            // Enables Contactless Transactions
                strcpy(data_1.transactionID, "3830\0");           // required if COMPLETION, VOID, RETURN.  Otherwise, leave blank
                strcpy(data_1.referenceNumber, "112233445566\0"); // required value. Set a reference number
                strcpy(data_1.terminalID, "12345\0");             // required value.  Set a terminal identifer
                strcpy(data_1.ticketNumber, "54321\0");           // required value. Set a ticket number
                data_1.duplicateCheck    = 0;                     // set to TRUE if you want to check for duplicate transactions
                data_1.duplicateOverride = 1;                     // set to TRUE if you want to allow duplicate charges to same card

                data_1.storeTransaction = 0;                      // If storeTransaction = true, store it instead of sending to WorldPay
//                strcpy(data_1.storagePassword, "WorldPay\0");         // if storagePassword = value, encrypt the stored file
                strcpy(data_1.storagePassword, "\0");
                strcpy(data_1.storageMemo, "\0");
//                sprintf(data_1.storageMemo, "WorldPay%d", counter++);
                data_1.storeOnHostNetworkError = 0;               // if storeOnHostNetworkError = true, store the transaction automatically if the network down or bad response from WorldPay

                int requestMode_1 = 1; // 0 = Return Gateway Response
                                     // 1 = Return Request + Gateway Response
                                     // 2 = Return Request Only

                r = executeTransaction(&data_1, WorldPayCallback, requestMode_1);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Execute WP Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Execute Transaction Succeeded\n");
                }


//                postWP(NULL, 0, data_1.storageMemo, strlen(data_1.storageMemo), "WorldPay", strlen("WorldPay"));
//                r = forwardTransaction(NULL, 0, data_1.storageMemo, strlen(data_1.storageMemo), "WorldPay", strlen("WorldPay"));
//                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
//                    char strErr[200] = { 0 };
//                    memset(strErr, 0, 200);
//                    device_getIDGStatusCodeString(r, strErr);
//                    printf(
//                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Execute WP Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
//                        strErr);
//                } else {
//                    printf("Forward Transaction Succeeded\n");
//                }

                fflush(stdout);
                break;
            case 21:
                printf(">>21. WorldPay QuickChip Start Transaction\n");

                WorldPayData data_2;
                strcpy(data_2.accountID, "1188346\0");
                strcpy(data_2.accountToken, "E1EB3EFB049DFB599F1CB454E1CFC4FD14BF90BCE74456AE9E9490D7D609B466C81A3801\0");
                strcpy(data_2.acceptorID, "364798674\0");
                data_2.transactionType = TRANSACTION_TYPE_QUICK_CHIP_START;
                // data_2.transactionType = TRANSACTION_TYPE_PRE_AUTH;
                // data_2.transactionType = TRANSACTION_TYPE_COMPLETION;
                // data_2.transactionType = TRANSACTION_TYPE_VOID;
                // data_2.transactionType = TRANSACTION_TYPE_RETURN;
                // data_2.transactionType = TRANSACTION_TYPE_CREDIT;
                // data_2.transactionType = TRANSACTION_TYPE_SALE;
                // data_2.transactionType = TRANSACTION_TYPE_QUICK_CHIP_FINISH;
                strcpy(data_2.amount, "22.00\0");                 // specify transaction Amount
                data_2.timeout = 30;                              // Timeout for transaction
                data_2.isTest  = 1;                               // if test transaction, set to TRUE.  If live transactions, set to FALSE
                data_2.msrOnly = 0;                               // for EMV + MSR, set to FALSE.  If MSR swipe only, set to TRUE
                data_2.enableCTLS = 1;                            // Enables Contactless Transactions
                strcpy(data_2.transactionID, "3830\0");           // required if COMPLETION, VOID, RETURN.  Otherwise, leave blank
                strcpy(data_2.referenceNumber, "112233445566\0"); // required value. Set a reference number
                strcpy(data_2.terminalID, "12345\0");             // required value.  Set a terminal identifer
                strcpy(data_2.ticketNumber, "54321\0");           // required value. Set a ticket number
                data_2.duplicateCheck    = 0;                     // set to TRUE if you want to check for duplicate transactions
                data_2.duplicateOverride = 1;                     // set to TRUE if you want to allow duplicate charges to same card

                data_1.storeTransaction = 0;                      // If storeTransaction = true, store it instead of sending to WorldPay
                strcpy(data_1.storagePassword, "\0");             // if storagePassword = value, encrypt the stored file
                strcpy(data_1.storageMemo, "\0");                 // If storageMemo = value, add that to the directory for that file
                data_1.storeOnHostNetworkError = 0;               // if storeOnHostNetworkError = true, store the transaction automatically if the network down or bad response from WorldPay

                int requestMode_2 = 1; // 0 = Return Gateway Response
                                     // 1 = Return Request + Gateway Response
                                     // 2 = Return Request Only

                r = executeTransaction(&data_2, WorldPayCallback, requestMode_2);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Execute WP Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Execute Transaction Succeeded\n");
                }
                fflush(stdout);
                break;
            case 22:
                printf(">>22. WorldPay QuickChip Finish Transaction\n");

                WorldPayData data;
                strcpy(data.accountID, "1188346\0");
                strcpy(data.accountToken, "E1EB3EFB049DFB599F1CB454E1CFC4FD14BF90BCE74456AE9E9490D7D609B466C81A3801\0");
                strcpy(data.acceptorID, "364798674\0");
                data.transactionType = TRANSACTION_TYPE_QUICK_CHIP_FINISH;
                // data.transactionType = TRANSACTION_TYPE_PRE_AUTH;
                // data.transactionType = TRANSACTION_TYPE_COMPLETION;
                // data.transactionType = TRANSACTION_TYPE_VOID;
                // data.transactionType = TRANSACTION_TYPE_RETURN;
                // data.transactionType = TRANSACTION_TYPE_CREDIT;
                // data.transactionType = TRANSACTION_TYPE_QUICK_CHIP_START;
                // data.transactionType = TRANSACTION_TYPE_SALE;
                strcpy(data.amount, "22.00\0");                 // specify transaction Amount
                data.timeout = 30;                              // Timeout for transaction
                data.isTest  = 1;                               // if test transaction, set to TRUE.  If live transactions, set to FALSE
                data.msrOnly = 0;                               // for EMV + MSR, set to FALSE.  If MSR swipe only, set to TRUE
                data.enableCTLS = 1;                            // Enables Contactless Transactions
                strcpy(data.transactionID, "3830\0");           // required if COMPLETION, VOID, RETURN.  Otherwise, leave blank
                strcpy(data.referenceNumber, "112233445566\0"); // required value. Set a reference number
                strcpy(data.terminalID, "12345\0");             // required value.  Set a terminal identifer
                strcpy(data.ticketNumber, "54321\0");           // required value. Set a ticket number
                data.duplicateCheck    = 0;                     // set to TRUE if you want to check for duplicate transactions
                data.duplicateOverride = 1;                     // set to TRUE if you want to allow duplicate charges to same card

                data_1.storeTransaction = 0;                      // If storeTransaction = true, store it instead of sending to WorldPay
                strcpy(data_1.storagePassword, "\0");             // if storagePassword = value, encrypt the stored file
                strcpy(data_1.storageMemo, "\0");                 // If storageMemo = value, add that to the directory for that file
                data_1.storeOnHostNetworkError = 0;               // if storeOnHostNetworkError = true, store the transaction automatically if the network down or bad response from WorldPay

                int requestMode = 1; // 0 = Return Gateway Response
                                     // 1 = Return Request + Gateway Response
                                     // 2 = Return Request Only

                r = executeTransaction(&data, WorldPayCallback, requestMode);
                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getIDGStatusCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Execute WP Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Execute Transaction Succeeded\n");
                }

                fflush(stdout);
                break;
            case 23: {
                 printf(">>23. Cancel WorldPay Transaction\n");
                 r = cancelWorldPay();
                 if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                     printf("  Do cancelWorldPay(), failed! Error Code: %04X\n", r);
                 } else {
                     printf("Cancel WorldPay Transaction Succeeded\n");
                 }
                 fflush(stdout);
                }
                break;
            case 24: {
                printf(">>24. Update Firmware\n");
                fflush(stdout);
                char firmware_file_name[50];
                memset(firmware_file_name, 0, 50);
                printf("Please enter the firmware file name (Ex. VP3300 Audio Jack NEO v1.01.067_USBHID.txt):\n");
                fflush(stdout);
                fgets(firmware_file_name, 50, stdin);
                int i;
                for (i = 49; i >= 0; i--) {
                    if (firmware_file_name[i] == '\n' || firmware_file_name[i] == '\r') {
                        firmware_file_name[i] = '\0';
                        break;
                    }
                }
                printf("Firmware File Name: %s\n", firmware_file_name);
                FILE * fp;
                if (NULL == (fp = fopen(firmware_file_name, "r"))) {
                    printf("Could not open file %s\n", firmware_file_name);
                    fflush(stdout);
                    break;
                }
                fflush(stdout);

                char firmwareData[_FIRMWARE_BUF_LEN];
                memset(firmwareData, 0, _FIRMWARE_BUF_LEN);
                int fw_lines = 0;
                int idx      = 0;
                char * line  = firmware_file_name;
                char temp[_FIRMWARE_CMD_LEN];
                while (!feof(fp) && strcmp(line, "END>")) {
                    if (idx >= _FIRMWARE_BUF_LEN) {
                        break;
                    }
                    memset(temp, 0, _FIRMWARE_CMD_LEN);
                    fgets(temp, _FIRMWARE_CMD_LEN, fp);
                    for (i = (_FIRMWARE_CMD_LEN) -1; i >= 0; i--) {
                        if (temp[i] == '\n' || temp[i] == '\r') {
                            temp[i] = '\0';
                            break;
                        }
                    }
                    line = temp;
                    strcpy(&(firmwareData[idx]), temp);
                    fw_lines++;
                    idx += strlen(temp) + 1;
                }
                fclose(fp);
                if (idx >= _FIRMWARE_BUF_LEN) {
                    printf("Not enough buffer\n");
                    fflush(stdout);
                    break;
                }
                printf("\033[1;31mUpdating firmware, please do not unplug the reader or exit this demo...\033[0m\n");
                fflush(stdout);
                r = device_updateFirmware(firmwareData, idx, NULL, 0, NULL, 0);

                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                    if (r == IDG_P2_STATUS_CODE_FW_INIT_SUCCESS) {
                        printf(
                            "\033[1;31mInitialize Firmware Update succeeded, please go back to Interface Select Options menu after the reader is reconnected, reselect USB and then reselect the same device through Device Select Options menu, and do Update Firmware again.\033[0m\n");
                    } else {
                        printf("\033[1;31mFirmware Update failed!\033[0m\n");
                        printf("Error code: 0x%04X\n", r);
                    }
                } else {
                    mssleep(3000);
                    printf("\033[1;31mFirmware Update succeeded.  Please exit the demo and reboot the reader.\033[0m\n");
                }
                fflush(stdout);
            }
            break;
//            case 25:
//                printf(">>25. WorldPay Forward Transaction\n");
////                r = forwardTransaction(WorldPayCallback, data_1.storageMemo, strlen(data_1.storageMemo), "WorldPay", strlen("WorldPay"), 0);
////                r = forwardTransaction(WorldPayCallback, "WorldPay7", strlen("WorldPay7"), NULL, 0, 0);
//                r = forwardTransaction(WorldPayCallback, "WorldPay7", strlen("WorldPay7"), "WorldPay", strlen("WorldPay"), 0);
//                if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
//                    char strErr[200] = { 0 };
//                    memset(strErr, 0, 200);
//                    device_getIDGStatusCodeString(r, strErr);
//                    printf(
//                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Execute WP Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
//                        strErr);
//                } else {
//                    printf("Forward Transaction Succeeded\n");
//                }
//
//                fflush(stdout);
//                break;
            case 0:
                printf(">>0.Back To Main Menu\n");
                fflush(stdout);
                break;
        }
    } while (choice != 0);
    // #ifdef WIN32
    if (choice == 0) {
//        idtech_process.pProcess_function_list();
        return;
    }
    // #endif
} /* _VP3300_process_device */

void
_VP3300_display_device_menu() {
    idtech_display_menu_from_lib.pDisplay_Menu_current = _VP3300_display_device_menu;

    if (device_getCurrentDeviceType() == IDT_DEVICE_VP3300_AJ) {
        printf("\t\t********** Device Options [VP3300 AJ]***********\n");
    } else if (device_getCurrentDeviceType() == IDT_DEVICE_VP3300_USB) {
        printf("\t\t********** Device Options [VP3300 USB]**********\n");
    } else if (device_getCurrentDeviceType() == IDT_DEVICE_VP3300_BT) {
        printf("\t\t********** Device Options [VP3300 BT]***********\n");
    } else if (device_getCurrentDeviceType() == IDT_DEVICE_VP3300_COM) {
        printf("\t\t********** Device Options [VP3300 COM]**********\n");
    }
    printf("\t\t0.  Back To Main Menu\n");
    printf("\t\t1.  Start Transaction\n");
    printf("\t\t2.  Cancel Transaction\n");
    printf("\t\t3.  Get Transaction Results\n");
    printf("\t\t4.  Get Firmware Version\n");
    printf("\t\t5.  Send Data Command\n");
    printf("\t\t6.  Get Serial Number\n");
    printf("\t\t7.  Ping Device\n");
    printf("\t\t8.  Interface Control\n");
    printf("\t\t9.  Enable Passthrough\n");
    printf("\t\t10. Disable Passthrough\n");
    printf("\t\t11. Burst Mode ON\n");
    printf("\t\t12. Burst Mode OFF\n");
    printf("\t\t13. Auto Poll\n");
    printf("\t\t14. Poll On Demand\n");
    printf("\t\t15. Set Merchant Record\n");
    printf("\t\t16. Get Merchant Record\n");
    printf("\t\t17. Set Date Time\n");
    printf("\t\t18. Get Date Time\n");
    printf("\t\t19. Start Remote Key Injection\n");
    printf("\t\t20. WorldPay Sale Transaction\n");
    printf("\t\t21. WorldPay QuickChip Start Transaction\n");
    printf("\t\t22. WorldPay QuickChip Finish Transaction\n");
    printf("\t\t23. Cancel WorldPay Transaction\n");
    printf("\t\t24. Update Firmware (Need to run twice)\n");
//    printf("\t\t25. WorldPay Forward Transaction\n");
    printf("\t\t************************************************\n");
    fflush(stdout);
} /* _VP3300_display_device_menu */
