/**
 * CAN 控制器实现
 */

#include "can/CANController.h"
#include <iostream>
#include <cstring>

using namespace std;

CANController::CANController(DWORD device_type, DWORD device_index, DWORD can_index)
    : m_device_type(device_type)
    , m_device_index(device_index)
    , m_can_index(can_index)
    , m_initialized(false)
    , m_callback(nullptr)
{
}

CANController::~CANController() {
    Close();
}

bool CANController::Initialize(BYTE baud_t0, BYTE baud_t1, BYTE mode) {
    if (m_initialized) {
        cerr << "警告：CAN 设备已经初始化" << endl;
        return true;
    }

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

    // 2. 初始化 CAN 参数
    cout << "配置 CAN 参数..." << endl;
    VCI_INIT_CONFIG config;
    memset(&config, 0, sizeof(VCI_INIT_CONFIG));

    config.AccCode = 0x00000000;    // 验收码
    config.AccMask = 0xFFFFFFFF;    // 屏蔽码（接收所有）
    config.Filter = 1;               // 滤波方式：接收所有类型
    config.Timing0 = baud_t0;        // 波特率定时器0
    config.Timing1 = baud_t1;        // 波特率定时器1
    config.Mode = mode;              // 工作模式

    ret = VCI_InitCAN(m_device_type, m_device_index, m_can_index, &config);
    if (ret != 1) {
        cerr << "错误：初始化 CAN 失败！" << endl;
        VCI_CloseDevice(m_device_type, m_device_index);
        return false;
    }

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

    // 4. 清空缓冲区
    VCI_ClearBuffer(m_device_type, m_device_index, m_can_index);

    m_initialized = true;
    cout << "CAN 设备初始化成功！" << endl;
    return true;
}

void CANController::Close() {
    if (!m_initialized) {
        return;
    }

    // 复位 CAN
    VCI_ResetCAN(m_device_type, m_device_index, m_can_index);

    // 关闭设备
    VCI_CloseDevice(m_device_type, m_device_index);

    m_initialized = false;
    cout << "CAN 设备已关闭" << endl;
}

bool CANController::SendStandardFrame(UINT can_id, const BYTE* data, BYTE len) {
    if (!m_initialized) {
        cerr << "错误：CAN 设备未初始化！" << endl;
        return false;
    }

    VCI_CAN_OBJ frame;
    memset(&frame, 0, sizeof(VCI_CAN_OBJ));

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

    if (data != nullptr && len > 0) {
        memcpy(frame.Data, data, frame.DataLen);
    }

    DWORD ret = VCI_Transmit(m_device_type, m_device_index, m_can_index, &frame, 1);
    return (ret == 1);
}

bool CANController::SendExtendedFrame(UINT can_id, const BYTE* data, BYTE len) {
    if (!m_initialized) {
        cerr << "错误：CAN 设备未初始化！" << endl;
        return false;
    }

    VCI_CAN_OBJ frame;
    memset(&frame, 0, sizeof(VCI_CAN_OBJ));

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

    if (data != nullptr && len > 0) {
        memcpy(frame.Data, data, frame.DataLen);
    }

    DWORD ret = VCI_Transmit(m_device_type, m_device_index, m_can_index, &frame, 1);
    return (ret == 1);
}

DWORD CANController::Receive(std::vector<VCI_CAN_OBJ>& frames, DWORD max_count) {
    if (!m_initialized) {
        cerr << "错误：CAN 设备未初始化！" << endl;
        return 0;
    }

    frames.resize(max_count);

    DWORD ret = VCI_Receive(m_device_type, m_device_index, m_can_index,
                            frames.data(), max_count, 0);

    if (ret > 0) {
        frames.resize(ret);  // 调整为实际接收到的数量

        // 如果设置了回调函数，调用它
        if (m_callback) {
            for (const auto& frame : frames) {
                m_callback(frame);
            }
        }
    } else {
        frames.clear();
    }

    return ret;
}

DWORD CANController::GetReceiveNum() {
    if (!m_initialized) {
        return 0;
    }
    return VCI_GetReceiveNum(m_device_type, m_device_index, m_can_index);
}

bool CANController::ClearBuffer() {
    if (!m_initialized) {
        return false;
    }
    DWORD ret = VCI_ClearBuffer(m_device_type, m_device_index, m_can_index);
    return (ret == 1);
}

bool CANController::GetDeviceInfo(VCI_BOARD_INFO& info) {
    if (!m_initialized) {
        return false;
    }
    DWORD ret = VCI_ReadBoardInfo(m_device_type, m_device_index, &info);
    return (ret == 1);
}
