#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/select.h>
#endif

#define SERIAL_PORT "/dev/ttyUSB0"  // Windows: "COM3"
#define BAUD_RATE 9600
#define BUFFER_SIZE 256

// 串口句柄
#ifdef _WIN32
HANDLE hSerial;
#else
int serial_fd;
#endif

// 初始化串口
int init_serial(const char *port, int baudrate) {
#ifdef _WIN32
    // Windows实现
    char full_port[20];
    snprintf(full_port, sizeof(full_port), "\\\\.\\%s", port);
    
    hSerial = CreateFile(full_port,
                        GENERIC_READ | GENERIC_WRITE,
                        0,
                        0,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        0);
    
    if (hSerial == INVALID_HANDLE_VALUE) {
        fprintf(stderr, "无法打开串口 %s\n", port);
        return -1;
    }
    
    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        fprintf(stderr, "获取串口状态失败\n");
        CloseHandle(hSerial);
        return -1;
    }
    
    dcbSerialParams.BaudRate = baudrate;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    
    if (!SetCommState(hSerial, &dcbSerialParams)) {
        fprintf(stderr, "设置串口参数失败\n");
        CloseHandle(hSerial);
        return -1;
    }
    
    COMMTIMEOUTS timeouts = {0};
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 50;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 50;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    
    SetCommTimeouts(hSerial, &timeouts);
    
#else
    // Linux/macOS实现
    serial_fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
    if (serial_fd == -1) {
        perror("无法打开串口");
        return -1;
    }
    
    struct termios options;
    tcgetattr(serial_fd, &options);
    
    cfsetispeed(&options, baudrate);
    cfsetospeed(&options, baudrate);
    
    options.c_cflag &= ~PARENB;   // 无奇偶校验
    options.c_cflag &= ~CSTOPB;   // 1个停止位
    options.c_cflag &= ~CSIZE;    // 清除数据位掩码
    options.c_cflag |= CS8;       // 8个数据位
    options.c_cflag &= ~CRTSCTS;  // 无硬件流控
    options.c_cflag |= CREAD | CLOCAL; // 启用接收器
    
    options.c_iflag &= ~(IXON | IXOFF | IXANY); // 禁用软件流控
    options.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始模式
    
    options.c_oflag &= ~OPOST; // 原始输出
    
    tcsetattr(serial_fd, TCSANOW, &options);
#endif
    
    printf("串口 %s 初始化成功，波特率 %d\n", port, baudrate);
    return 0;
}

// 发送命令
void send_command(const char *command) {
    printf("\n发送: %s\n", command);
    
#ifdef _WIN32
    char cmd_buffer[BUFFER_SIZE];
    DWORD bytes_written;
    snprintf(cmd_buffer, sizeof(cmd_buffer), "%s\r\n", command);
    WriteFile(hSerial, cmd_buffer, strlen(cmd_buffer), &bytes_written, NULL);
#else
    char cmd_buffer[BUFFER_SIZE];
    snprintf(cmd_buffer, sizeof(cmd_buffer), "%s\r\n", command);
    write(serial_fd, cmd_buffer, strlen(cmd_buffer));
#endif
    
    usleep(500000); // 500ms延迟
}

// 读取响应
void read_response() {
    char buffer[BUFFER_SIZE];
    int bytes_read = 0;
    
#ifdef _WIN32
    DWORD bytes_read_win;
    if (ReadFile(hSerial, buffer, BUFFER_SIZE - 1, &bytes_read_win, NULL)) {
        bytes_read = bytes_read_win;
    }
#else
    fd_set read_fds;
    struct timeval timeout;
    
    FD_ZERO(&read_fds);
    FD_SET(serial_fd, &read_fds);
    
    timeout.tv_sec = 0;
    timeout.tv_usec = 100000; // 100ms超时
    
    if (select(serial_fd + 1, &read_fds, NULL, NULL, &timeout) > 0) {
        bytes_read = read(serial_fd, buffer, BUFFER_SIZE - 1);
    }
#endif
    
    if (bytes_read > 0) {
        buffer[bytes_read] = '\0';
        printf("收到: %s\n", buffer);
    } else {
        printf("无响应\n");
    }
}

// 关闭串口
void close_serial() {
#ifdef _WIN32
    if (hSerial != INVALID_HANDLE_VALUE) {
        CloseHandle(hSerial);
    }
#else
    if (serial_fd != -1) {
        close(serial_fd);
    }
#endif
    printf("串口已关闭\n");
}

// 测试函数
void test_all_commands() {
    printf("=== LED控制器测试开始 ===\n\n");
    
    // 1. 帮助命令
    printf("1. 测试 HELP 命令:\n");
    send_command("HELP");
    read_response();
    
    // 2. 模式切换
    printf("\n2. 测试模式切换:\n");
    const char *modes[] = {"WHITE", "WARM", "NATURAL", NULL};
    for (int i = 0; modes[i] != NULL; i++) {
        send_command(modes[i]);
        read_response();
        sleep(1);
    }
    
    // 3. 亮度调节
    printf("\n3. 测试亮度调节:\n");
    for (int i = 0; i < 3; i++) {
        send_command("HIGH");
        read_response();
        usleep(500000);
    }
    for (int i = 0; i < 3; i++) {
        send_command("LOW");
        read_response();
        usleep(500000);
    }
    
    // 4. GEAR命令
    printf("\n4. 测试 GEAR 命令:\n");
    int gears[] = {0, 32, 64, 96, 128, -1};
    for (int i = 0; gears[i] != -1; i++) {
        char cmd[20];
        snprintf(cmd, sizeof(cmd), "GEAR %d", gears[i]);
        send_command(cmd);
        read_response();
        usleep(500000);
    }
    
    // 5. 状态查询
    printf("\n5. 测试 STATUS 命令:\n");
    send_command("STATUS");
    read_response();
    
    // 6. 关闭输出
    printf("\n6. 测试 OFF 命令:\n");
    send_command("OFF");
    read_response();
    
    printf("\n=== 测试完成 ===\n");
}

int main() {
    if (init_serial(SERIAL_PORT, BAUD_RATE) != 0) {
        return 1;
    }
    
    test_all_commands();
    
    close_serial();
    return 0;
}