#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cmsis_os2.h"
#include "kmdw_console.h"

extern int hw_test_gpio_run(void);
extern int hw_test_spi_run(void);
extern int hw_test_i2c_run(void);
extern int hw_test_pwm_adc_run(void);

void ip_test_all_thread(void *arg) {
    int res_gpio, res_spi, res_i2c, res_pwm_adc;

    osDelay(1000);

    kmdw_printf("\n\n");
    kmdw_printf("************************************************\n");
    kmdw_printf("*          KL520 IP Verification Auto-Test     *\n");
    kmdw_printf("************************************************\n");
    kmdw_printf("Please ensure all loopback jumpers are connected:\n");
    kmdw_printf("1. GPIO Loopbacks (P37-P36, P34-P32, P27-P26, P35-P38)\n");
    kmdw_printf("2. SPI0 Loopback (MOSI - MISO)\n");
    kmdw_printf("3. PWM-ADC Loopback (P29 - ADC3)\n");
    kmdw_printf("4. I2C Sensor connected (OV5647)\n");
    kmdw_printf("Test starting in 3 seconds...\n");
    osDelay(3000);

    kmdw_printf("\n>>> Running GPIO Test...\n");
    res_gpio = hw_test_gpio_run();

    kmdw_printf("\n>>> Running SPI Test...\n");
    osDelay(10);
    res_spi = hw_test_spi_run();

    kmdw_printf("\n>>> Running I2C Test...\n");
    osDelay(10);
    res_i2c = hw_test_i2c_run();

    kmdw_printf("\n>>> Running PWM-ADC Test...\n");
    osDelay(10);
    res_pwm_adc = hw_test_pwm_adc_run();

    kmdw_printf("\n\n");
    kmdw_printf("================================================\n");
    kmdw_printf("              Auto-Test Summary                 \n");
    kmdw_printf("================================================\n");
    kmdw_printf(" GPIO Test    : %s\n", res_gpio == 0 ? "PASS" : "FAIL");
    kmdw_printf(" SPI Test     : %s\n", res_spi == 0 ? "PASS" : "FAIL");
    kmdw_printf(" I2C Test     : %s\n", res_i2c == 0 ? "PASS" : "FAIL");
    kmdw_printf(" PWM-ADC Test : %s\n", res_pwm_adc == 0 ? "PASS" : "FAIL");
    kmdw_printf("================================================\n");
    osDelay(10);
    while (1) {
        kmdw_printf("\n");
        kmdw_printf("--------------------------------\n");
        kmdw_printf("      IP Verification Menu      \n");
        kmdw_printf("--------------------------------\n");
        kmdw_printf(" [1] GPIO Test\n");
        kmdw_printf(" [2] SPI Test\n");
        kmdw_printf(" [3] I2C Test\n");
        kmdw_printf(" [4] PWM-ADC Test\n");
        kmdw_printf(" [5] Run All Auto-Test Again\n");
        kmdw_printf("--------------------------------\n");
        kmdw_printf("Select test: ");
        osDelay(10);

        char buf[64];
        int ch = 0;
  
        memset(buf, 0, sizeof(buf));
        kmdw_console_echo_gets(buf, sizeof(buf));

        char *token = strtok(buf, " \r\n\t");
        if (token) ch = atoi(token);

        switch (ch) {
            case 1: hw_test_gpio_run(); break;
            case 2: hw_test_spi_run(); break;
            case 3: hw_test_i2c_run(); break;
            case 4: hw_test_pwm_adc_run(); break;
            case 5:
                kmdw_printf("\n>>> Running GPIO Test...\n");
                res_gpio = hw_test_gpio_run();
                kmdw_printf("\n>>> Running SPI Test...\n");
                res_spi = hw_test_spi_run();
                kmdw_printf("\n>>> Running I2C Test...\n");
                res_i2c = hw_test_i2c_run();
                kmdw_printf("\n>>> Running PWM-ADC Test...\n");
                res_pwm_adc = hw_test_pwm_adc_run();

                kmdw_printf("================================================\n");
                kmdw_printf(" GPIO: %s | SPI: %s | I2C: %s | PWM-ADC: %s\n",
                    res_gpio == 0 ? "PASS" : "FAIL",
                    res_spi == 0 ? "PASS" : "FAIL",
                    res_i2c == 0 ? "PASS" : "FAIL",
                    res_pwm_adc == 0 ? "PASS" : "FAIL");
                break;
            default: kmdw_printf("Invalid selection.\n"); break;
        }
        osDelay(500);
    }
}

void ip_test_all_init(void) {

    const osThreadAttr_t attr = {
        .name = "IP_Test_All",
        .stack_size = 2048,
        .priority = osPriorityNormal,
    };
    osThreadNew(ip_test_all_thread, NULL, &attr);
}
