#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <pthread.h>
#include <dirent.h>
#include <signal.h>
#include <sys/stat.h> // 放在现有 #include 区域任意位置
#include <stdint.h>   // 就有 uint8_t

#define DEBUG 0 /* 1=打开调试  0=关闭打印 */
#if DEBUG
#define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define DBG(fmt, ...) \
    do                \
    {                 \
    } while (0)
#endif

#define BUFFER_SIZE 4096
#define SEND_SIZE 1024

static char g_rxbuf[BUFFER_SIZE] = {0};                        /* 最新一帧数据（普通文本） */
static char g_rxbuf_hex[BUFFER_SIZE] = {0};                    /* 最新一帧数据（16进制） */
static int g_rxlen = 0;                                        /* 有效长度     */
static int g_rxHexlen = 0;                                     /* 有效长度     */
static pthread_mutex_t g_rx_mutex = PTHREAD_MUTEX_INITIALIZER; /* 互斥锁 */

/*  ---------------- 串口底层 ----------------  */
/**
 * @brief 接收数据
 * @param fd 串口描述符
 * @return 接收到的数据
 */
char *uart_recv(int fd)
{
    static char ret[BUFFER_SIZE];
    pthread_mutex_lock(&g_rx_mutex);
    if (g_rxlen > 0)
    {
        memcpy(ret, g_rxbuf, g_rxlen + 1);
        g_rxlen = 0; /* 消费掉 */
    }
    else
    {
        ret[0] = '\0'; /* 暂无数据 */
    }
    // DBG("Received Text Data: %s\n", ret); // 打印接收到的普通文本数据
    pthread_mutex_unlock(&g_rx_mutex);
    return ret;
}

/**
 * @brief 以16进制形式读取数据
 * @param fd 串口描述符
 * @return 16进制字符串
 */
char *uart_recv_hex(int fd)
{
    static char ret[BUFFER_SIZE * 3 + 1]; // 每个字节需要2个字符表示16进制，加上空字符
    pthread_mutex_lock(&g_rx_mutex);
    if (g_rxHexlen > 0)
    {
        for (int i = 0; i < g_rxHexlen; i++)
        {
            sprintf(&ret[i * 2], "%02X", (unsigned char)g_rxbuf_hex[i]);
        }
        ret[g_rxHexlen * 2] = '\0'; // 添加空字符
        g_rxHexlen = 0;             /* 消费掉 */
        //  DBG("Received Hex Data: %s\n", ret); // 打印接收到的16进制数据
    }
    else
    {
        ret[0] = '\0'; /* 暂无数据 */
    }
    pthread_mutex_unlock(&g_rx_mutex);
    return ret;
}

/**
 * @brief 接收线程函数
 * @param arg 串口文件描述符
 * @return NULL
 */
// static void *rx_thread(void *arg)
// {
//     int fd = (int)(long)arg;
//     char tmp[BUFFER_SIZE];
//     int n;

//     while ((n = read(fd, tmp, sizeof(tmp))) > 0) {
//         pthread_mutex_lock(&g_rx_mutex);
//         if (n > BUFFER_SIZE - 1) n = BUFFER_SIZE - 1;
//         tmp[n] = '\0';
//         DBG("Received Text Data: %s\n", tmp);
//         g_rxlen = n;
//         g_rxHexlen = n;
//         memcpy(g_rxbuf, tmp, n + 1);
//         memcpy(g_rxbuf_hex, tmp, n + 1);   /* 16进制 */
//         pthread_mutex_unlock(&g_rx_mutex);
//     }
//     return NULL;
// }

// 4800 -- 115200 通信优化
/* 在 rx_thread.c 里增加 */
static void submit_frame_with_fix(const unsigned char *line, int n)
{
    pthread_mutex_lock(&g_rx_mutex);

    /* 先原样放进缓冲区 */
    int len = n;
    memcpy(g_rxbuf, line, len);

    /* 修复帧尾：单 0D0A → 双 0D0D0A0A */
    if (len >= 2 &&
        g_rxbuf[len - 2] == 0x0D &&
        g_rxbuf[len - 1] == 0x0A)
    {
        g_rxbuf[len - 2] = 0x0D;
        g_rxbuf[len - 1] = 0x0D;
        g_rxbuf[len] = 0x0A;
        g_rxbuf[len + 1] = 0x0A;
        len += 2;
    }

    /* 统一更新长度和三份缓冲区 */
    g_rxlen = len;
    g_rxHexlen = len;
    memcpy(g_rxbuf_hex, g_rxbuf, len); /* 现在长度已 fix */

    pthread_mutex_unlock(&g_rx_mutex);
}
// 4800 -- 115200 通信优化  canonical
//  static void *rx_thread(void *arg)
//  {
//      int fd = (int)(long)arg;
//      char line[BUFFER_SIZE];

//     for (;;)
//     {
//         /* canonical 下 read 会一次性返回一行（含 \n） */
//         ssize_t n = read(fd, line, sizeof(line) - 1);
//         if (n <= 0) continue;

//         line[n] = '\0';          /* 给 DBG 用 */

//         /* 简单校验：头俩字节 "AT"，尾两字节 "\r\n" */
//         if (n >= 4 &&
//             line[0] == 'A' && line[1] == 'T' &&
//             line[n-2] == '\r' && line[n-1] == '\n')
//         {
//             // pthread_mutex_lock(&g_rx_mutex);
//             // g_rxlen = g_rxHexlen = n;
//             // memcpy(g_rxbuf,     line, n);
//             // memcpy(g_rxbuf_hex, line, n);
//             // pthread_mutex_unlock(&g_rx_mutex);
//             submit_frame_with_fix(line, n);   /* 修复+提交 */

//             /* 日志 */
//             DBG("[FRAME] %zd B: %s", n, line);
//         }
//         else
//         {
//             DBG("[SKIP]  %zd B: %s", n, line);
//         }
//     }
//     return NULL;
// }

// raw
static void *rx_thread(void *arg)
{
    int fd = (int)(long)arg;
    uint8_t fifo[BUFFER_SIZE];
    int wp = 0;

    for (;;)
    {
        uint8_t ch;
        ssize_t n = read(fd, &ch, 1); /* 阻塞到 1 字节 */
        if (n <= 0)
            continue;

        fifo[wp++] = ch; /* 原样保存，含 0x00 0x0D 0x7F … */
        if (wp >= BUFFER_SIZE)
            wp = 0; /* 简单回绕，防止溢出 */

        DBG("[FIFO] len=%d: ", wp);
        for (int i = 0; i < wp; ++i)
            DBG("%02X ", fifo[i]);
        DBG("\n");
        /* 判帧尾：收到 0x0A 就认为一帧结束（可按需要改成 0x0D 0x0A） */
        // if (ch == 0x0A) {
        if (wp >= 2 &&
            fifo[wp - 2] == 0x0D &&
            fifo[wp - 1] == 0x0A)
        {
            submit_frame_with_fix((const unsigned char *)fifo, wp);
            wp = 0; /* 准备收下一帧 */
        }
    }
    return NULL;
}
// static void *rx_thread(void *arg)
// {
//     int fd = (int)(long)arg;
//     uint8_t fifo[BUFFER_SIZE];
//     int wp = 0;

//     /* 帧尾模板：0D 0D 0A 0A */
//     static const uint8_t tail[4] = {0x0D, 0x0D, 0x0A, 0x0A};

//     for (;;) {
//         uint8_t ch;
//         ssize_t n = read(fd, &ch, 1);
//         if (n <= 0) continue;

//         fifo[wp++] = ch;
//         if (wp >= BUFFER_SIZE) wp = 0;   /* 回绕保护 */

//         /* 只有末尾 4 字节完全匹配时才提交 */
//           DBG("[FIFO] len=%d: ", wp);
//     for (int i = 0; i < wp; ++i)
//         DBG("%02X ", fifo[i]);
//     DBG("\n");
//         if (wp >= 4 &&
//             fifo[wp - 4] == tail[0] &&
//             fifo[wp - 3] == tail[1] &&
//             fifo[wp - 2] == tail[2] &&
//             fifo[wp - 1] == tail[3])
//         {
//             submit_frame_with_fix(fifo, wp);   /* 此时长度已是 128+2=130 */
//             wp = 0;                            /* 准备下一帧 */
//         }
//     }
//     return NULL;
// }

/**
 * @brief       配置已打开串口的波特率及 8N1+无流控+阻塞超时参数
 * @param[in]   fd       : 串口文件描述符（已被 open）
 * @param[in]   baudrate : speed_t 波特率，如 B115200
 * @return      0 成功，-1 失败
 */
int init_serial(int fd, speed_t baudrate)
{
    struct termios tty;
    if (tcgetattr(fd, &tty) != 0)
        return -1;
    cfmakeraw(&tty);
    cfsetispeed(&tty, baudrate);
    cfsetospeed(&tty, baudrate);

    tty.c_cflag &= ~PARENB; /* 8N1 */
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8 | CREAD | CLOCAL;
    tty.c_cflag &= ~CRTSCTS; /* 无流控 */
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tty.c_oflag &= ~OPOST;
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 50;

    return tcsetattr(fd, TCSANOW, &tty);
}

/**
 * @brief 把字符串数字波特率转成 speed_t
 * @param str 例如 "115200"
 * @return speed_t，非法返回 B0
 */
static speed_t baud_str2speed(const char *str)
{
    unsigned long b = strtoul(str, NULL, 10);
    switch (b)
    {
    case 4800: /* ← 新增 */
        return B4800;
    case 9600:
        return B9600;
    case 19200:
        return B19200;
    case 38400:
        return B38400;
    case 57600:
        return B57600;
    case 115200:
        return B115200;
#ifdef B230400
    case 230400:
        return B230400;
#endif
#ifdef B460800
    case 460800:
        return B460800;
#endif
    default:
        return B0; /* 非法 */
    }
}

/**
 * @brief  打开并初始化串口（阻塞模式）
 * @param  port     设备路径，如 "/dev/ttyS1"
 * @param  baud_str 波特率字符串，如 "115200"
 * @return >=0 成功返回 fd；<0 失败
 */
int uart_init(const char *port, const char *baud_str)
{
    speed_t spd = baud_str2speed(baud_str);
    if (spd == B0)
        return -1;
    int fd = open(port, O_RDWR | O_NOCTTY);
    if (fd < 0)
        return -1;
    if (init_serial(fd, spd) != 0)
    {
        close(fd);
        return -1;
    }
    /* 1. 丢弃上下电残留字节
       2. 清空内核接收/发送队列
       3. 等待硬件 FIFO 排空 */
    tcflush(fd, TCIOFLUSH);
    tcdrain(fd);

    pthread_t tid;
    pthread_create(&tid, NULL, rx_thread, (void *)(long)fd);
    pthread_detach(tid); /* 自生自灭 */
    return fd;
}

/**
 * @brief 关闭串口
 * @param fd 串口描述符
 */
void uart_close(int fd)
{
    if (fd >= 0)
        close(fd);
}

/**
 * @brief 发送数据
 * @param fd 串口描述符
 * @param data 数据指针
 * @param len 数据长度
 * @return 成功发送的字节数
 */
int uart_send(int fd, const char *data, int len)
{
    const char *p = data;
    int n = 0;
    while (n < len)
    {
        ssize_t r = write(fd, p + n, len - n);
        if (r <= 0)
            return -1;
        n += r;
    }
    tcdrain(fd);
    // DBG("TX:%.*s  (%d bytes)\n", len, p, len);
    return 1;
}

/* 新增：释放指定 TTY 的占用进程 */
int kill_tty_user(const char *tty)
{
    DBG("kill_tty_user: %s\n", tty);
    DIR *dir;
    struct dirent *ent;
    char path[64], link[256];
    int killed = 0;

    if (!(dir = opendir("/proc")))
        return 0;

    while ((ent = readdir(dir)))
    {
        if (ent->d_name[0] < '0' || ent->d_name[0] > '9')
            continue;

        snprintf(path, sizeof(path), "/proc/%s/fd", ent->d_name);
        DIR *fd_dir = opendir(path);
        if (!fd_dir)
            continue;

        struct dirent *fd_ent;
        while ((fd_ent = readdir(fd_dir)))
        {
            if (fd_ent->d_name[0] == '.')
                continue;
            snprintf(link, sizeof(link), "%s/%s", path, fd_ent->d_name);
            char real[256];
            ssize_t r = readlink(link, real, sizeof(real) - 1);
            if (r > 0)
            {
                real[r] = 0;
                if (strcmp(real, tty) == 0)
                {
                    pid_t pid = atoi(ent->d_name);
                    if (pid > 1)
                    {
                        kill(pid, SIGKILL);
                        killed++;
                    }
                }
            }
        }
        closedir(fd_dir);
    }
    closedir(dir);
    return killed;
}

void pwm_uart_init(void)
{
    struct stat st;
    char pwm_path[128];
    snprintf(pwm_path, sizeof(pwm_path), "/sys/class/pwm/pwmchip0/pwm2");
    if (stat(pwm_path, &st) != 0)
    {
        system("echo 2 > /sys/class/pwm/pwmchip0/export");
    }
    system("echo 5000 > /sys/class/pwm/pwmchip0/pwm2/period");
    system("echo 2500 > /sys/class/pwm/pwmchip0/pwm2/duty_cycle");
    system("echo normal > /sys/class/pwm/pwmchip0/pwm2/polarity");
    system("echo 1 > /sys/class/pwm/pwmchip0/pwm2/enable");
}

// 4800 -- 115200 通信优化
/*
 * 把已打开的串口设为 canonical 模式（行缓冲），
 * 行结束符='\n'，保持 4800 8N1 不变
 */
void uart_set_canonical(int fd)
{
    DBG("[CANON] uart_set_canonical\n");
    struct termios t;

    if (tcgetattr(fd, &t) < 0)
    {
        perror("tcgetattr");
        return;
    }

    /* 打开 canonical 模式，让驱动拼到 \n 再一次性返回 */
    t.c_lflag |= ICANON; /* 规范输入 */
    t.c_cc[VEOL] = '\n'; /* 附加行结束符（可省，默认就是 \n） */
    t.c_cc[VEOF] = 0;    /* 禁用 EOF 字符，防止提前返回 */
    t.c_cc[VMIN] = 0;    /* canonical 下 VM   IN/VTIME 被忽略 */
    t.c_cc[VTIME] = 0;

    /* 保持 raw 输出，避免回显、信号等干扰 */
    t.c_lflag &= ~(ECHO | ECHONL | ISIG);

    t.c_oflag &= ~OPOST;

    if (tcsetattr(fd, TCSANOW, &t) < 0)
        perror("tcsetattr canonical");
    else
        DBG("[CANON] 4800 8N1 canonical mode enabled\n");
}
void uart_set_raw(int fd)
{
    DBG("[RAW] uart_set_raw\n");
    struct termios t;

    if (tcgetattr(fd, &t) < 0)
    {
        perror("tcgetattr");
        return;
    }

    cfmakeraw(&t); /* 已经帮我们关掉 ICANON ECHO … 所有标志 */

    t.c_cflag &= ~CRTSCTS; /* 保持无流控 */
    t.c_iflag &= ~(IXON | IXOFF | IXANY);
    t.c_cc[VMIN] = 1;  /* 收到 1 字节就返回 */
    t.c_cc[VTIME] = 0; /* 不设超时 */

    if (tcsetattr(fd, TCSANOW, &t) < 0)
        perror("tcsetattr raw");
    else
        DBG("[RAW] 4800 8N1 raw mode enabled\n");
}

int main(void)
{
    const char *port = "/dev/ttyS0";

    /* 1. 先释放占用（不改动任何原有函数） */
    int killed = kill_tty_user(port);
    if (killed > 0)
    {
        DBG("Killed %d process(es) using %s, waiting 200 ms...\n", killed, port);
        usleep(200000);
    }

    pwm_uart_init();
    // int killed = kill_tty_user(port);
    // if (killed > 0) {
    //     DBG("Killed %d process(es) using %s, waiting 200 ms...\n", killed, port);/*  */
    //     usleep(200000);
    // }

    int fd = uart_init(port, "4800");
    if (fd < 0)
    {
        perror("uart_init");
        return -1;
    }
    /* ******** 在这里切 canonical ******** */
    // uart_set_canonical(fd);
    uart_set_raw(fd);
    for (;;)
    {
        sleep(1);

        char *txt = uart_recv(fd);
        if (txt[0])
        {
            DBG("TXT: %s\n", txt);
        }

        char *txthex = uart_recv_hex(fd);
        if (txthex[0])
        {
            DBG("TXTHEX : %s\n", txthex);
        }

        if (strstr(txt, "TEST_START"))
            uart_send(fd, "+START\r\n", 8); /* 回 AT */
        DBG("TX:+START\r\n");
        // fflush(stdout);          /* ← 只加这一行 */
    }
    uart_close(fd);
    return 0;
}