/**
 * CAN 通信完整示例程序
 * 功能：演示如何使用 ControlCAN 库进行 CAN 通信
 */

#include <iostream>
#include <cstring>
#include <thread>
#include <chrono>
#include "../../lib/ControlCAN.h"

using namespace std;

// CAN 设备配置参数
#define DEVICE_TYPE     VCI_USBCAN2     // 设备类型：USBCAN-2
#define DEVICE_INDEX    0               // 设备索引：第一个设备
#define CAN_INDEX       0               // CAN 通道索引：CAN0

// 常用波特率配置（Timing0, Timing1）
// 250Kbps: 0x01, 0x1C
// 500Kbps: 0x00, 0x1C
// 1Mbps:   0x00, 0x14
#define BAUD_250K_T0    0x01
#define BAUD_250K_T1    0x1C

/**
 * 初始化并打开 CAN 设备
 * @return 成功返回 true，失败返回 false
 */
bool InitCAN() {
    cout << "=== 初始化 CAN 设备 ===" << endl;

    // 1. 打开设备
    cout << "1. 打开设备..." << endl;
    DWORD ret = VCI_OpenDevice(DEVICE_TYPE, DEVICE_INDEX, 0);
    if (ret != 1) {
        cerr << "错误：打开设备失败！" << endl;
        return false;
    }
    cout << "   设备打开成功！" << endl;

    // 2. 配置 CAN 参数
    cout << "2. 配置 CAN 参数..." << endl;
    VCI_INIT_CONFIG config;
    config.AccCode = 0x00000000;        // 验收码：接收所有帧
    config.AccMask = 0xFFFFFFFF;        // 屏蔽码：不过滤
    config.Filter = 1;                  // 滤波方式：双滤波
    config.Timing0 = BAUD_250K_T0;      // 波特率：250Kbps
    config.Timing1 = BAUD_250K_T1;
    config.Mode = 0;                    // 模式：正常模式
    config.Reserved = 0;

    ret = VCI_InitCAN(DEVICE_TYPE, DEVICE_INDEX, CAN_INDEX, &config);
    if (ret != 1) {
        cerr << "错误：初始化 CAN 失败！" << endl;
        VCI_CloseDevice(DEVICE_TYPE, DEVICE_INDEX);
        return false;
    }
    cout << "   CAN 初始化成功（波特率：250Kbps）！" << endl;

    // 3. 启动 CAN
    cout << "3. 启动 CAN..." << endl;
    ret = VCI_StartCAN(DEVICE_TYPE, DEVICE_INDEX, CAN_INDEX);
    if (ret != 1) {
        cerr << "错误：启动 CAN 失败！" << endl;
        VCI_CloseDevice(DEVICE_TYPE, DEVICE_INDEX);
        return false;
    }
    cout << "   CAN 启动成功！" << endl;

    // 4. 清空缓冲区
    VCI_ClearBuffer(DEVICE_TYPE, DEVICE_INDEX, CAN_INDEX);
    cout << "   缓冲区已清空！" << endl;

    return true;
}

/**
 * 发送 CAN 报文
 * @param can_id CAN ID
 * @param data 数据指针
 * @param len 数据长度（最大8字节）
 * @param extend 是否为扩展帧
 * @return 成功返回 true，失败返回 false
 */
bool SendCANFrame(UINT can_id, const BYTE* data, BYTE len, bool extend = false) {
    VCI_CAN_OBJ send_frame;
    memset(&send_frame, 0, sizeof(VCI_CAN_OBJ));

    send_frame.ID = can_id;
    send_frame.SendType = 0;            // 正常发送
    send_frame.RemoteFlag = 0;          // 数据帧
    send_frame.ExternFlag = extend ? 1 : 0;  // 标准帧/扩展帧
    send_frame.DataLen = len > 8 ? 8 : len;

    if (data != nullptr) {
        memcpy(send_frame.Data, data, send_frame.DataLen);
    }

    DWORD ret = VCI_Transmit(DEVICE_TYPE, DEVICE_INDEX, CAN_INDEX, &send_frame, 1);
    if (ret != 1) {
        cerr << "错误：发送 CAN 报文失败！" << endl;
        return false;
    }

    return true;
}

/**
 * 接收 CAN 报文
 * @param timeout_ms 超时时间（毫秒）
 * @return 接收到的报文数量
 */
int ReceiveCANFrames(int timeout_ms = 100) {
    VCI_CAN_OBJ receive_frames[100];  // 接收缓冲区

    // 获取接收缓冲区中的数据数量
    DWORD num = VCI_GetReceiveNum(DEVICE_TYPE, DEVICE_INDEX, CAN_INDEX);
    if (num == 0) {
        return 0;
    }

    // 读取数据
    DWORD ret = VCI_Receive(DEVICE_TYPE, DEVICE_INDEX, CAN_INDEX,
                            receive_frames, 100, timeout_ms);

    if (ret > 0) {
        cout << "接收到 " << ret << " 帧数据：" << endl;
        for (DWORD i = 0; i < ret; i++) {
            VCI_CAN_OBJ& frame = receive_frames[i];

            cout << "  [" << i + 1 << "] ";
            cout << "ID=0x" << hex << frame.ID << dec;
            cout << " (";
            cout << (frame.ExternFlag ? "扩展帧" : "标准帧");
            cout << (frame.RemoteFlag ? ", 远程帧" : ", 数据帧");
            cout << ") ";
            cout << "长度=" << (int)frame.DataLen << " ";
            cout << "数据=[";
            for (int j = 0; j < frame.DataLen; j++) {
                printf("%02X", frame.Data[j]);
                if (j < frame.DataLen - 1) cout << " ";
            }
            cout << "]" << endl;
        }
        return ret;
    }

    return 0;
}

/**
 * 读取并显示设备信息
 */
void ShowDeviceInfo() {
    VCI_BOARD_INFO board_info;
    DWORD ret = VCI_ReadBoardInfo(DEVICE_TYPE, DEVICE_INDEX, &board_info);

    if (ret == 1) {
        cout << "\n=== 设备信息 ===" << endl;
        cout << "硬件版本: " << board_info.hw_Version << endl;
        cout << "固件版本: " << board_info.fw_Version << endl;
        cout << "驱动版本: " << board_info.dr_Version << endl;
        cout << "接口库版本: " << board_info.in_Version << endl;
        cout << "CAN 通道数: " << (int)board_info.can_Num << endl;
        cout << "序列号: " << board_info.str_Serial_Num << endl;
        cout << "硬件类型: " << board_info.str_hw_Type << endl;
    } else {
        cerr << "读取设备信息失败！" << endl;
    }
}

/**
 * 关闭 CAN 设备
 */
void CloseCAN() {
    cout << "\n=== 关闭 CAN 设备 ===" << endl;

    // 复位 CAN
    VCI_ResetCAN(DEVICE_TYPE, DEVICE_INDEX, CAN_INDEX);
    cout << "CAN 已复位" << endl;

    // 关闭设备
    VCI_CloseDevice(DEVICE_TYPE, DEVICE_INDEX);
    cout << "设备已关闭" << endl;
}

/**
 * 主程序 - 完整的 CAN 通信流程示例
 */
int main() {
    cout << "================================================" << endl;
    cout << "       CAN 通信完整示例程序" << endl;
    cout << "================================================" << endl;

    // ===== 步骤 1: 初始化设备 =====
    if (!InitCAN()) {
        cerr << "初始化失败，程序退出！" << endl;
        return -1;
    }

    // ===== 步骤 2: 读取设备信息 =====
    ShowDeviceInfo();

    // ===== 步骤 3: 发送 CAN 报文 =====
    cout << "\n=== 发送 CAN 报文 ===" << endl;

    // 示例 1: 发送标准帧
    BYTE data1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    cout << "发送标准帧 (ID=0x123)..." << endl;
    if (SendCANFrame(0x123, data1, 8, false)) {
        cout << "  发送成功！数据: [01 02 03 04 05 06 07 08]" << endl;
    }

    this_thread::sleep_for(chrono::milliseconds(10));

    // 示例 2: 发送扩展帧
    BYTE data2[] = {0xAA, 0xBB, 0xCC, 0xDD};
    cout << "发送扩展帧 (ID=0x12345678)..." << endl;
    if (SendCANFrame(0x12345678, data2, 4, true)) {
        cout << "  发送成功！数据: [AA BB CC DD]" << endl;
    }

    this_thread::sleep_for(chrono::milliseconds(10));

    // 示例 3: 发送控制命令（模拟 AGV 速度控制）
    BYTE agv_cmd[] = {0x10, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00};
    // 假设: 字节0=命令类型(0x10=速度控制), 字节2-3=速度值(50=0x32)
    cout << "发送 AGV 速度控制命令 (ID=0x200)..." << endl;
    if (SendCANFrame(0x200, agv_cmd, 8, false)) {
        cout << "  发送成功！速度设置为 50" << endl;
    }

    // ===== 步骤 4: 接收 CAN 报文 =====
    cout << "\n=== 接收 CAN 报文 ===" << endl;
    cout << "开始监听 CAN 总线（持续 5 秒）..." << endl;

    auto start_time = chrono::steady_clock::now();
    int total_received = 0;

    while (true) {
        auto current_time = chrono::steady_clock::now();
        auto elapsed = chrono::duration_cast<chrono::seconds>(current_time - start_time).count();

        if (elapsed >= 5) {
            break;  // 5秒后退出
        }

        int count = ReceiveCANFrames(100);
        total_received += count;

        this_thread::sleep_for(chrono::milliseconds(100));
    }

    cout << "监听结束，共接收 " << total_received << " 帧数据。" << endl;

    // ===== 步骤 5: 关闭设备 =====
    CloseCAN();

    cout << "\n程序执行完成！" << endl;
    return 0;
}
