/*
 * Copyright (C) ID TECH.
 *
 * Author: Eric
 *
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "demo_common.h"
#ifndef WIN32
# include <dlfcn.h>
#endif
#include "libIDT_Device.h"
#include <pthread.h>

// void process_device_select();
// void process_exit();
// void display_main_menu();
void
display_tcpip_menu();
void
process_tcpip_device_select();

extern void
MSR_callBack(int type, IDTMSRData cardData1);
extern void
MSR_callBackp(int type, IDTMSRData * cardData1);
extern void
PIN_callBack(int type, IDTPINData * pinData);
extern void
RKI_callBack(int resultCode, char * macValue);
extern void
LCD_callBack(int type, IDTLCDItem * lcdItem);
// extern char* getDeviceType(int deviceType);
extern int
inputSelection();
extern void
process_exit();
// extern int level;
extern IDT_COMMON_PROCESS Demo_Common_Process;
extern IDT_DEMO_LIB_DISPLAY_MENU idtech_display_menu_from_lib;

// IDT_COMMON_PROCESS Demo_Common_Process;

// IDT_DEMO_LIB_DISPLAY_MENU idtech_display_menu_from_lib;

typedef void (* Demo_Init)(IDT_COMMON_PROCESS pCommonProcess, IDT_DEMO_LIB_DISPLAY_MENU * idtech_display_menu_from_lib);
typedef void (* Demo_getMenuFn)(IDT_DEMO_LIB_DISPLAY_MENU * idtech_display_menu_from_lib);

extern Demo_Init demo_init;
extern Demo_getMenuFn demo_getMenuFn;

int devicetype      = IDT_DEVICE_UNKNOWN;
int port_number     = 0;
char ip_address[20] = { 0 };
int rcode = 0;

void
init_tcpip_demo_lib(int deviceType) {
    Demo_Common_Process.main_display_device_list   = display_tcpip_menu;
    Demo_Common_Process.main_process_device_select = process_tcpip_device_select;
    Demo_Common_Process.PIN_callBack  = PIN_callBack;
    Demo_Common_Process.LCD_callBack  = LCD_callBack;
    Demo_Common_Process.FW_callBack   = FW_callBack;
    Demo_Common_Process.RKI_callBack  = RKI_callBack;
    Demo_Common_Process.CMR_callBack  = CMR_callBack;
    Demo_Common_Process.CSFS_callBack = CSFS_callBack;
    Demo_Common_Process.SendDataLog   = SendDataLog;
    Demo_Common_Process.ReadDataLog   = ReadDataLog;

    // MSR
    Demo_Common_Process.printMSRData  = printMSRData;
    Demo_Common_Process.MSR_callBack  = MSR_callBack;
    Demo_Common_Process.MSR_callBackp = MSR_callBackp;

    // EMV
    Demo_Common_Process.printBytes = printBytes;
    Demo_Common_Process.printTLV   = printTLV;
    Demo_Common_Process.convertBytesIntoHexStr = convertBytesIntoHexStr;
    Demo_Common_Process.convertHStrIntoHex     = convertHStrIntoHex;
    Demo_Common_Process.EMV_callBack = EMV_callBack;

    Demo_Common_Process.set_emv_Finished = set_emv_Finished;
    Demo_Common_Process.get_emv_Finished = get_emv_Finished;

    Demo_Common_Process.set_pin_Finished = set_pin_Finished;
    Demo_Common_Process.get_pin_Finished = get_pin_Finished;

    Demo_Common_Process.getDUKPT = getDUKPT;

    Demo_Common_Process.inputSelection = inputSelection;

    Demo_Common_Process.printAIDList = printAIDList;

    char libname[256] = { 0 };

    switch (deviceType) {
        #ifdef WIN32
        case IDT_DEVICE_NEO2_TCPIP:
        case IDT_DEVICE_NEO2_TCPIP + 1:
        case IDT_DEVICE_NEO2_TCPIP + 2:
        case IDT_DEVICE_NEO2_TCPIP + 3:
        case IDT_DEVICE_NEO2_TCPIP + 4:
            sprintf(libname, "libNEO2.dll");
            break;

        #endif /* ifdef WIN32 */
        #ifdef __linux
        case IDT_DEVICE_NEO2_TCPIP:
        case IDT_DEVICE_NEO2_TCPIP + 1:
        case IDT_DEVICE_NEO2_TCPIP + 2:
        case IDT_DEVICE_NEO2_TCPIP + 3:
        case IDT_DEVICE_NEO2_TCPIP + 4:
            sprintf(libname, "libNEO2.so");
            break;
        #endif /* ifdef __linux */
        #ifdef __MACH__
        case IDT_DEVICE_NEO2_TCPIP:
        case IDT_DEVICE_NEO2_TCPIP + 1:
        case IDT_DEVICE_NEO2_TCPIP + 2:
        case IDT_DEVICE_NEO2_TCPIP + 3:
        case IDT_DEVICE_NEO2_TCPIP + 4:
            sprintf(libname, "libNEO2.dylib");
            break;
        #endif /* ifdef __MACH__ */
        default:
            break;
    }

    #ifdef WIN32
    void * h = LoadLibrary(libname);
    if (h == NULL) {
        fprintf(stderr, "fail to load %s\n", libname);
        fflush(stdout);
        return;
    }
    #else
    void * h = dlopen(libname, RTLD_LAZY);
    if (h == NULL) {
        fprintf(stderr, "fail to load %s\n", libname);
        fflush(stdout);
        return;
    }
    #endif /* ifdef WIN32 */

    #ifdef WIN32
    demo_init      = (Demo_Init) GetProcAddress(h, "libDemo_init");
    demo_getMenuFn = (Demo_getMenuFn) GetProcAddress(h, "libDemo_getMenuFn");
    demo_init(Demo_Common_Process, &idtech_display_menu_from_lib);
    #else
    demo_init      = (Demo_Init) dlsym(h, "libDemo_init");
    demo_getMenuFn = (Demo_getMenuFn) dlsym(h, "libDemo_getMenuFn");
    #endif
    demo_init(Demo_Common_Process, &idtech_display_menu_from_lib);
} /* init_tcpip_demo_lib */

int
tcpip_init() {
    int r = RETURN_CODE_ERR_DISCONNECT;
    int i = 0;

    while (r != RETURN_CODE_DO_SUCCESS) {
        process_tcpip_device_select();
        if (rcode) {
            return 0;
        }
        //		r = tcpip_device_init(deviceType, comport_number, baudrate);
        r = tcpip_device_init(devicetype, port_number, ip_address);
        if (r != RETURN_CODE_DO_SUCCESS) {
            printf("  Fail to init TCPIP!\n");
            fflush(stdout);
        }
    }
    init_tcpip_demo_lib(devicetype);
    return 0;
}

void
process_tcpip_device_select() {
    int choice;

    process_exit();

    // Get The Device Type
    devicetype = IDT_DEVICE_UNKNOWN;
    do {
        display_tcpip_menu();

        choice = inputSelection();
        if (choice > 0 && choice < 2) {
            switch (choice) {
                case 1:
                    devicetype = IDT_DEVICE_NEO2_TCPIP;
                    break;
            }
            char port[10];
            printf("Please enter the IP address\n");
            fflush(stdout);
            fgets(ip_address, 20, stdin);
            printf("Please enter the port number\n");
            fflush(stdout);
            fgets(port, 10, stdin);
            port_number = atoi(port);
            rcode       = 0;
            return;
        } else if (choice == 0)      {
            //			process_exit();
            rcode = 1;
            return;
        }
    } while (choice != 0);
} /* process_tcpip_device_select */

void
display_tcpip_menu() {
    idtech_display_menu_from_lib.pDisplay_Menu_current = display_tcpip_menu;
    int i = 0;
    printf("\t\t************************************************\n");
    printf("\t\t*********** IDT Universal SDK ******************\n");
    printf("\t\t****** RS 232 Device Select Options ************\n");
    printf("\t\t0.  Back To Interface Menu\n");
    printf("\t\t1.  NEO2\n");
    printf("\t\t************************************************\n");
    fflush(stdout);
}

// void process_exit()
// {
//	device_close();
//
//	printf("Application Exit.\n");
//	fflush(stdout);
// }
