#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include "usb2200.h"

void Show();

int main(int argc, char **argv)
{
	int handle, err;
  WORD pid = USB2255_32;
  BYTE bid = 0x0;
  char input[64];
  DWORD options;

  handle = USB2200_OpenDevice(pid, bid);
	if(handle < 0) {
		printf("open failed, error code %d\n", handle);
		return 0;
	}

  Show();

  while (1){
    printf("\nPress ESC to exit.\n\n");

    if (scanf("%u", &options) != 1) break;
    int c = getchar();
    if (c == 27) break;

    switch (options){
      case 1: {
        printf("--- Get Library Version ---\n");

        char* version = USBIO_GetLibraryVersion();

        if (version == NULL) {
          printf("Error: Failed to retrieve library version.\n");
          break;
        }

        printf("USB-2200 Library Version: %s\n", version);
    
        break;
      }

      case 2:{
        printf("--- Load to Default Setting ---\n");
        err = USB2200_LoadDefault(handle);
        if(err) {
          printf("USB2200_LoadDefault Error number %d\n", err);
          break;
        }
        break;
      }

      case 3: {
        char desc[33] = {0};
        WORD ret;

        printf("\n--- Device Description Name Configuration ---\n");

        /* Step 1: Read-First */
        ret = USB2200_GetDeviceNickName(handle, desc);
        if (ret == NO_ERR) {
          printf(">> Current Name: \"%s\"\n", desc);
        } else {
          printf(">> Error: Failed to read description (0x%04X)\n", ret);
        }

        /* Step 2: Interactive Prompt */
        printf("Enter new name (Max 32 chars, Enter to skip): ");
        if (fgets(input, sizeof(input), stdin) && input[0] != '\n') {
          /* Remove newline character from fgets */
          input[strcspn(input, "\n")] = 0;
            
          ret = USB2200_SetDeviceNickName(handle, input);
          if (ret == NO_ERR) {
            printf(">> Success: Device name updated.\n");
          } else {
            printf(">> Error: Failed to update name (0x%04X)\n", ret);
          }
        }
        break;
      }

      case 4: { /* [Get/Set] Watchdog Timeout Value */
        DWORD current_timeout = 0;
        DWORD set_timeout = 0;
        WORD ret;

        printf("\n--- Software Watchdog Timeout ---\n");

        /* Step 1: Read-First */
        ret = USB2200_GetSoftWDTTimeout(handle, &current_timeout);
        if (ret == NO_ERR) {
          printf(">> Current Timeout: %u ms\n", current_timeout);
        } else {
          printf(">> Error: Failed to read timeout (0x%04X)\n", ret);
        }

        /* Step 2: Interactive Prompt */
        printf("Set Timeout (Range 100-1800000 ms, Enter to skip): ");
        if (fgets(input, sizeof(input), stdin) && input[0] != '\n') {
          if (input[0] == '-') {
            printf(">> Error: Negative value not allowed.\n");
            break;
          }

          set_timeout = (DWORD)strtoul(input, NULL, 0);

          /* Logic Check */
          if (set_timeout < 100 || set_timeout > 1800000) {
            printf(">> Warning: Value out of recommended range!\n");
          }

          ret = USB2200_SetSoftWDTTimeout(handle, set_timeout);
          if (ret == NO_ERR) {
            printf(">> Success: Watchdog timeout updated to %u ms.\n", set_timeout);
          } else {
            printf(">> Error: Set failed (0x%04X)\n", ret);
          }
        }
        break;
      }

      case 5:{
        while (1) {
          char input[8];

          printf("--- SYNC Device (press ESC to exit) ---\n");
          printf("Press any key to sync: ");

          if (!fgets(input, sizeof(input), stdin))
            continue;

          // ESC . ASCII . 27
          if (input[0] == 27)
            break;

          err = USB2200_SYNCDevice(handle);
          if(err) {
            printf("USB2200_SYNCDevice Error number %d\n", err);
            break;
          }
        }
        break;
      }

      case 6:{
        printf("--- Clear WDT Err LED ---\n");
        err = USB2200_ClearWDTErrLED(handle);
        if(err) {
          printf("USB2200_ClearWDTErrLED Error number %d\n", err);
          break;
        }
        break;
      }

      case 7: { /* [Get] Firmware Version (0x2000) */
        WORD fw_version = 0;
        WORD ret;

        printf("\n--- Firmware Information ---\n");

        ret = USB2200_GetFwVer(handle, &fw_version);

        if (ret == NO_ERR) {
        /* * %X: . 16 ...........
         * 0x0105 -> 1.5
         * 0x0A0B -> A.B
         * 0x006A -> 0.6A
         */
         printf(">> Firmware Version: %X.%X\n", 
                (BYTE)(fw_version >> 8), (BYTE)(fw_version & 0xFF));
        } else {
          printf(">> Error: Failed to retrieve Firmware Version (0x%04X)\n", ret);
        }
        break;
      }

      case 8: { /* [Read Only] Get Firmware Date */
        char fw_date[11] = {0};
        WORD ret;

        printf("\n--- Firmware Release Date ---\n");
      
        ret = USB2200_GetFwDate(handle, fw_date);
      
        if (ret == NO_ERR) {
          /* Directly print the string */
          printf(">> Firmware Date: %s\n", fw_date);
        } else {
          printf(">> Error: Failed to retrieve Firmware Date (0x%04X)\n", ret);
        }
      
        break;
      }

      case 9: {
        BYTE o_byDOTotal;
        WORD ret;
        ret = USB2200_GetDOTotal(handle, &o_byDOTotal);
        if (ret != NO_ERR) {
            printf("Error: Get DO total channel failed (0x%04X)\n", ret);
            break;
        }
  
        printf("Get DO total channel:%d\n",o_byDOTotal);
        break;
      }

      case 10: {
        BYTE o_byDITotal;
        WORD ret;
        ret = USB2200_GetDITotal(handle, &o_byDITotal);
        if (ret != NO_ERR) {
            printf("Error: Get DI total channel failed (0x%04X)\n", ret);
            break;
        }
  
        printf("Get DI total channel:%d\n",o_byDITotal);
        break;
      }

      case 11: {
        BYTE o_byAOTotal;
        WORD ret;
        ret = USB2200_GetAOTotal(handle, &o_byAOTotal);
        if (ret != NO_ERR) {
            printf("Error: Get AO total channel failed (0x%04X)\n", ret);
            break;
        }
  
        printf("Get AO total channel:%d\n",o_byAOTotal);
        break;
      }

      case 12: {
        BYTE o_byAITotal;
        WORD ret;
        ret = USB2200_GetAITotal(handle, &o_byAITotal);
        if (ret != NO_ERR) {
            printf("Error: Get AI total channel failed (0x%04X)\n", ret);
            break;
        }
  
        printf("Get AI total channel:%d\n",o_byAITotal);
        break;
      }

      case 13: {
        BYTE o_byPOTotal;
        WORD ret;
        ret = USB2200_GetPOTotal(handle, &o_byPOTotal);
        if (ret != NO_ERR) {
            printf("Error: Get PO total channel failed (0x%04X)\n", ret);
            break;
        }
  
        printf("Get PO total channel:%d\n",o_byPOTotal);
        break;
      }

      case 14: {
        BYTE o_byPITotal;
        WORD ret;
        ret = USB2200_GetPITotal(handle, &o_byPITotal);
        if (ret != NO_ERR) {
            printf("Error: Get PO total channel failed (0x%04X)\n", ret);
            break;
        }
  
        printf("Get PI total channel:%d\n",o_byPITotal);
        break;
      }

      default:{
        Show();
        break;
      }
    }
  }

  USB2200_CloseDevice(handle);

	return 0;
}

void Show()
{
    printf("\n--- USB-2200 Module System Configuration ---\n");
    printf("1. [Get    ] Library Version\n");
    printf("2. [Action ] Factory Reset (Set Module Default) (A hot-plug (unplug and replug) of the device is required for this action to take effect.)\n");
    printf("3. [Get/Set] Device Description Name\n");
    printf("4. [Get/Set] Watchdog Timeout Value\n");
    printf("5. [Action ] SYNC Device\n");
    printf("6. [Action ] Clear Watchdog Error LED\n");
    printf("7. [Get    ] Firmware Version.\n");
    printf("8. [Get    ] Firmware Update Date.\n");
    printf("9. [Get    ] DO Total Channel.\n");
    printf("10.[Get    ] DI Total Channel.\n");
    printf("11.[Get    ] AO Total Channel.\n");
    printf("12.[Get    ] AI Total Channel.\n");
    printf("13.[Get    ] PO Total Channel.\n");
    printf("14.[Get    ] PI Total Channel.\n");
    printf("--------------------------------------------\n");
    printf("Others show this list, Q to return to main menu.\n");
    printf("Select an option: ");
}
