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

IDT_COMMON_PROCESS COMMON;
extern IDT_PROCESS idtech_process;
extern IDT_DEMO_LIB_DISPLAY_MENU idtech_display_menu_from_lib;

void
_SpectrumPro_display_device_menu();

void
_SpectrumPro_process_device() {
    int choice;
    int r = 0;
    char str1[256] = { 0 };
    int len        = 512;

    memset(str1, 0, 256);
    do {
        _SpectrumPro_display_device_menu();
        //		printf("Please Input your Selection:\n");
        //		scanf("%d",&choice);
        choice = COMMON.inputSelection();
        switch (choice) {
            case 1: {
                printf(">>1. Get Firmware Version\n");
                fflush(stdout);
                r = device_getFirmwareVersion(str1);
                if (r != RETURN_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getResponseCodeString(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 2: {
                printf(">>2. Reboot Device\n");
                fflush(stdout);
                r = device_rebootDevice();
                if (r != RETURN_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getResponseCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Reboot Device Failed! ErrorCode: 0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    char str2[200] = { 0 };
                    printf("Reboot Device Success!\n");
                }
                fflush(stdout);
            }
            break;
            case 3: {
                printf(">>3. Send Command: 0x76, 0x46,0x23\n");
                fflush(stdout);
                BYTE bbyte[5] = { 0x00 };
                int cmdlen;
                BYTE cmdData[_DATA_BUF_LEN] = { 0x00 };
                int cmdDataLen = 0;
                bbyte[0] = 0x76;
                bbyte[1] = 0x46;
                bbyte[2] = 0x23;
                cmdlen   = 5;
                //				BYTE rbbyte[512] = {0};
                //				memset(rbbyte,0,512);
                BYTE rbbyte[_DATA_BUF_LEN * 4 + 64] = { 0 };
                memset(rbbyte, 0, _DATA_BUF_LEN * 4 + 64);
                //				len=512;
                len = _DATA_BUF_LEN * 4 + 64;

                r = device_SendDataCommand(bbyte, cmdlen, cmdData, cmdDataLen, rbbyte, &len);
                if (r != RETURN_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getResponseCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Send Command Failed! ErrorCode: 0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    //					char str3[1024] = {0};
                    char str3[1024 * 8 + 64 * 2] = { 0 };
                    memset(str3, 0, 1024 * 8 + 64 * 2);
                    COMMON.convertBytesIntoHexStr(rbbyte, len, 0, str3);
                    printf("response code : %s\n", str3);
                }
                fflush(stdout);
            }
            break;
            case 4: {
                printf(">>4. Poll Card Reader\n");
                fflush(stdout);
                BYTE status[100] = { 0 };
                memset(status, 0, 100);
                len = 512;
                r   = device_pollCardReader(status);
                if (r != RETURN_CODE_DO_SUCCESS) {
                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getResponseCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Poll Card Reader Failed! ErrorCode: 0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    if ((status[0] & 0x01) == 0x01) {
                        printf("Device Manufacturing CA data valid\r\n");
                    }
                    if ((status[0] & 0x02) == 0x02) {
                        printf("Device Manufacturing Secure data valid\r\n");
                    }
                    if ((status[0] & 0x04) == 0x04) {
                        printf("HOST_CR_MASTER_DUKPT Key valid\r\n");
                    }
                    if ((status[0] & 0x08) == 0x08) {
                        printf("HOST_CR_MAC Keys valid(Authenticated)\r\n");
                    }
                    if ((status[0] & 0x40) == 0x40) {
                        printf("DATA_DUKPT Key Valid\r\n");
                    }
                    if ((status[0] & 0x80) == 0x80) {
                        printf("Key is initialized (MFK and RSA Key pairs)\r\n");
                    }
                    if ((status[1] & 0x01) == 0x01) {
                        printf("Firmware Key Valid\r\n");
                    }
                    if ((status[1] & 0x04) == 0x04) {
                        printf("CR_PINPAD_MASTER_DUKPT Key valid\r\n");
                    }
                    if ((status[1] & 0x08) == 0x08) {
                        printf("CR_PINPAD_MAC Keys valid(Authenticated)\r\n");
                    }
                    if ((status[1] & 0x10) == 0x10) {
                        printf("DATA Pairing DUKPT Key valid\r\n");
                    }
                    if ((status[1] & 0x20) == 0x20) {
                        printf("PIN Pairing DUKPT Key Valid\r\n");
                    }
                    if ((status[2] & 0x02) == 0x02) {
                        printf("Tamper Switch #1 Error\r\n");
                    }
                    if ((status[2] & 0x04) == 0x04) {
                        printf("Battery Backup Error\r\n");
                    }
                    if ((status[2] & 0x08) == 0x08) {
                        printf("Temperature Error\r\n");
                    }
                    if ((status[2] & 0x10) == 0x10) {
                        printf("Voltage Sensor Error\r\n");
                    }
                    if ((status[2] & 0x20) == 0x20) {
                        printf("Firmware Authentication Error\r\n");
                    }
                    if ((status[2] & 0x40) == 0x40) {
                        printf("Tamper Switch #2 Error\r\n");
                    }
                    if ((status[2] & 0x80) == 0x80) {
                        printf("Removal Tamper Error\r\n");
                    }
                    int v1 = (status[3] >> 4);
                    int v2 = (status[3] & 0x0f);
                    printf("Battery Voltage %d . %d V\r\n", v1, v2);
                    if ((status[4] & 0x01) == 0x01) {
                        printf("Log is Full\r\n");
                    }
                    if ((status[4] & 0x02) == 0x02) {
                        printf("Mag Data Present\r\n");
                    }
                    if ((status[4] & 0x04) == 0x04) {
                        printf("Card Insert\r\n");
                    }
                    if ((status[4] & 0x08) == 0x08) {
                        printf("Removal Sensor connected\r\n");
                    }
                    if ((status[4] & 0x10) == 0x10) {
                        printf("Card Seated\r\n");
                    }
                    if ((status[4] & 0x20) == 0x20) {
                        printf("Latch Mechanism Active\r\n");
                    }
                    if ((status[4] & 0x40) == 0x40) {
                        printf("Removal Sensor Active\r\n");
                    }
                    if ((status[4] & 0x80) == 0x80) {
                        printf("Tamper Detector Active\r\n");
                    }
                    if ((status[5] & 0x01) == 0x01) {
                        printf("SAM Available\r\n");
                    }
                    if ((status[5] & 0x02) == 0x02) {
                        printf("Chip Card Reader Available\r\n");
                    }
                    if ((status[5] & 0x04) == 0x04) {
                        printf("Host Connected\r\n");
                    }
                    if ((status[5] & 0x08) == 0x08) {
                        printf("Contactless Available\r\n");
                    }
                    if ((status[5] & 0x10) == 0x10) {
                        printf("PINPAD connected\r\n");
                    }
                    if ((status[5] & 0x20) == 0x20) {
                        printf("MSR Header connected\r\n");
                    }
                    if ((status[5] & 0x80) == 0x80) {
                        printf("Production Unit\r\n");
                    }
                }
                fflush(stdout);
            }
            break;
            case 5:
                printf(">>5. DUKPT KSN KEK\n");
                COMMON.getDUKPT(0);
                break;
            case 6:
                printf(">>6. DUKPT KSN DEK\n");
                COMMON.getDUKPT(2);
                break;
            case 7:
                printf(">>7. DUKPT KSN MAK\n");
                COMMON.getDUKPT(5);
                break;
            case 8:
                printf(">>8. DUKPT KSN REK\n");
                COMMON.getDUKPT(10);
                break;
            case 9:
                printf(">>9. DUKPT KSN HSM\n");
                COMMON.getDUKPT(20);
                break;
            case 10: {
                printf(">>10. Update Firmware for K21\n");
                char firmware_main_name[30];
                char firmware_file_name[30];
                printf("Please enter the main firmware file name (Ex. SP K21 APP V1.00.XXX):\n");
                fflush(stdout);
                //			getc(stdin);
                fgets(firmware_main_name, 30, stdin);
                int i;
                for (i = 0; i < 30; i++) {
                    if (firmware_main_name[i] == '\n' || firmware_main_name[i] == '\r') {
                        firmware_main_name[i] = '\0';
                        break;
                    }
                }
                int firmware_main_name_length = strlen(firmware_main_name);
                if (strncmp(firmware_main_name, "SP K21 APP V", 12) || firmware_main_name_length != 20) {
                    printf("Invalid file name: %s len %d\n", firmware_main_name, firmware_main_name_length);
                    fflush(stdout);
                    break;
                }
                strcpy(firmware_file_name, firmware_main_name);
                strcat(firmware_file_name, ".bin.sig");
                printf("Firmware File Name: %s\n", firmware_file_name);

                FILE * fp;
                if (NULL == (fp = fopen(firmware_file_name, "rb"))) {
                    printf("Could not open file %s\n", firmware_file_name);
                    fflush(stdout);
                    break;
                }

                BYTE firmwareData[_FIRMWARE_BUF_LEN];
                int fw_size = 0;

                fseek(fp, 0, SEEK_END);
                fw_size = ftell(fp);
                if (fw_size > _FIRMWARE_BUF_LEN) {
                    printf("Not enough buffer\n");
                    fflush(stdout);
                    break;
                }

                fseek(fp, 0, SEEK_SET);
                fread(firmwareData, fw_size, 1, fp);
                fclose(fp);
                //			long count = 1;
                //			while (1)  //test
                //			{
                //				printf("The %ld time\n", count);
                printf("Firmware file size: %d\n", fw_size);
                printf("Updating firmware, please do not unplug the reader...\n");
                r = device_updateFirmware(firmwareData, fw_size, firmware_main_name, 0, NULL, 0);
                if (r != RETURN_CODE_DO_SUCCESS) {
                    printf("Firmware update for K21 failed!\n");

                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getResponseCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Update Firmware for K21 Failed! ErrorCode: 0x%02x, Info: %s ----- \n", r,
                        strErr);

                    fflush(stdout);
                    break;
                } else {
                    printf("Firmware update for K21 succeeded\n");
                    fflush(stdout);
                }
                //				count++;
                //				mssleep(1500);
                //			}
            }
            break;
            case 11: {
                printf(">>11. Update Firmware for Max\n");
                char firmware_main_name[30];
                char firmware_file_name[30];
                printf("Please enter the main firmware file name (Ex. SP MAX APP V1.00.XXX):\n");
                fflush(stdout);
                //			getc(stdin);
                fgets(firmware_main_name, 30, stdin);
                int i;
                for (i = 0; i < 30; i++) {
                    if (firmware_main_name[i] == '\n' || firmware_main_name[i] == '\r') {
                        firmware_main_name[i] = '\0';
                        break;
                    }
                }
                int firmware_main_name_length = strlen(firmware_main_name);
                if (strncmp(firmware_main_name, "SP MAX APP V", 12) || firmware_main_name_length != 20) {
                    printf("Invalid file name: %s len %d\n", firmware_main_name, firmware_main_name_length);
                    break;
                }
                strcpy(firmware_file_name, firmware_main_name);
                strcat(firmware_file_name, ".bin.sig");
                printf("Firmware File Name: %s\n", firmware_file_name);
                fflush(stdout);
                FILE * fp;
                if (NULL == (fp = fopen(firmware_file_name, "rb"))) {
                    printf("Could not open file %s\n", firmware_file_name);
                    fflush(stdout);
                    break;
                }

                BYTE firmwareData[_FIRMWARE_BUF_LEN];
                int fw_size = 0;

                fseek(fp, 0, SEEK_END);
                fw_size = ftell(fp);
                if (fw_size > _FIRMWARE_BUF_LEN) {
                    printf("Not enough buffer\n");
                    fflush(stdout);
                    break;
                }

                fseek(fp, 0, SEEK_SET);
                fread(firmwareData, fw_size, 1, fp);
                fclose(fp);
                printf("Firmware file size: %d\n", fw_size);
                printf("Updating firmware, please do not unplug the reader...\n");
                fflush(stdout);
                r = device_updateFirmware(firmwareData, fw_size, firmware_main_name, 0, NULL, 0);
                if (r != RETURN_CODE_DO_SUCCESS) {
                    printf("Firmware update for Max failed!\n");

                    char strErr[200] = { 0 };
                    memset(strErr, 0, 200);
                    device_getResponseCodeString(r, strErr);
                    printf(
                        ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Update Firmware for Max Failed! ErrorCode: 0x%02x, Info: %s ----- \n", r,
                        strErr);
                } else {
                    printf("Firmware update for Max 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
} /* _SpectrumPro_process_device */

void
_SpectrumPro_display_device_menu() {
    idtech_display_menu_from_lib.pDisplay_Menu_current = _SpectrumPro_display_device_menu;
    printf("\t\t********* Device Options [SpectrumPro]*********\n");
    printf("\t\t0. Back To Main Menu\n");
    printf("\t\t1. Get Firmware Version\n");
    printf("\t\t2. Reboot Device\n");
    printf("\t\t3. Send Command\n");
    printf("\t\t4. Poll Card Reader\n");
    printf("\t\t5. DUKPT KSN KEK\n");
    printf("\t\t6. DUKPT KSN DEK\n");
    printf("\t\t7. DUKPT KSN MAK\n");
    printf("\t\t8. DUKPT KSN REK\n");
    printf("\t\t9. DUKPT KSN HSM\n");
    printf("\t\t10. Update Firmware for K21\n");
    printf("\t\t11. Update Firmware for Max\n");
    printf("\t\t************************************************\n");
    fflush(stdout);
}
