#include "mc/can_driver.h"
#include <cstring>
#include <stdexcept>
#include <iostream>
#include <thread>
#include <fcntl.h>  // 用于 fcntl
#include <unistd.h> // 用于 close 和 read

CANDriver::CANDriver() = default;

CANDriver::~CANDriver()
{
    close();
}

bool CANDriver::open(const std::string &interface)
{
    if (running)
    {
        return false;
    }

#ifdef _WIN32
    std::cerr << "Windows implementation not available\n";
    return false;
#else
    // Linux SocketCAN实现
    if ((sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
    {
        perror("socket");
        return false;
    }

    struct ifreq ifr;
    strcpy(ifr.ifr_name, interface.c_str());
    if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0)
    {
        perror("ioctl");
        ::close(sockfd);
        return false;
    }

    struct sockaddr_can addr;
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        ::close(sockfd);
        return false;
    }

    // 设置非阻塞模式
    int flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 设置为非阻塞

    running = true;
    receiveThread = std::thread(&CANDriver::receiveThreadFunc, this);
    return true;
#endif
}

void CANDriver::close()
{
    if (running)
    {
        running = false;
        if (receiveThread.joinable())
        {
            receiveThread.join();
        }

#ifdef _WIN32
        if (hCAN != INVALID_HANDLE_VALUE)
        {
            // CAN_Close(hCAN);
            hCAN = INVALID_HANDLE_VALUE;
        }
#else
        if (sockfd >= 0)
        {
            ::close(sockfd);
            sockfd = -1;
        }
#endif
    }
}

bool CANDriver::sendFrame(const CANFrame &frame)
{
    if (!running)
        return false;

#ifdef _WIN32
    // Windows发送实现
    return false;
#else
    struct can_frame raw_frame;
    memset(&raw_frame, 0, sizeof(raw_frame));

    raw_frame.can_id = frame.id;
    if (frame.ext)
        raw_frame.can_id |= CAN_EFF_FLAG;
    if (frame.rtr)
        raw_frame.can_id |= CAN_RTR_FLAG;
    raw_frame.can_dlc = frame.dlc;
    memcpy(raw_frame.data, frame.data, frame.dlc);

    // 设置非阻塞写操作
    int flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 设置为非阻塞

    if (write(sockfd, &raw_frame, sizeof(raw_frame)) != sizeof(raw_frame))
    {
        perror("write");
        return false;
    }
    return true;
#endif
}

void CANDriver::setReceiveCallback(ReceiveCallback callback, void *userData)
{
    this->callback = callback;
    this->userData = userData;
}

bool CANDriver::setFilter(const std::vector<can_filter> &filters)
{
#ifdef _WIN32
    return false;
#else
    if (!running)
        return false;

    filters_ = filters; // 更新本地保存
    return applyFilters();
#endif
}

bool CANDriver::addFilter(const can_filter &filter)
{
    filters_.push_back(filter);
    return applyFilters();
}

bool CANDriver::addFilters(const std::vector<can_filter> &filters)
{
    filters_.insert(filters_.end(), filters.begin(), filters.end());
    return applyFilters();
}

bool CANDriver::applyFilters()
{
#ifdef _WIN32
    return false;
#else
    if (!running)
        return false;

    if (filters_.empty())
    {
        // 如果没有设置过滤器，就关闭硬件过滤器（接受所有帧）
        setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, nullptr, 0);
        return true;
    }

    if (setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER,
                   filters_.data(), filters_.size() * sizeof(can_filter)) < 0)
    {
        perror("setsockopt");
        return false;
    }
    return true;
#endif
}

void CANDriver::receiveThreadFunc()
{
#ifdef _WIN32
    // Windows接收实现
#else
    struct can_frame raw_frame;
    while (running)
    {
        // 在非阻塞模式下读取数据
        ssize_t nbytes = read(sockfd, &raw_frame, sizeof(raw_frame));
        if (nbytes < 0)
        {
            if (errno != EAGAIN) // 非阻塞错误，忽略
            {
                perror("read");
            }
            continue; // 没有数据时继续循环
        }

        if (nbytes == sizeof(raw_frame) && callback)
        {
            CANFrame frame;
            frame.id = raw_frame.can_id & CAN_EFF_MASK;
            frame.ext = !!(raw_frame.can_id & CAN_EFF_FLAG);
            frame.rtr = !!(raw_frame.can_id & CAN_RTR_FLAG);
            frame.dlc = raw_frame.can_dlc;
            memcpy(frame.data, raw_frame.data, raw_frame.can_dlc);

            // 调用回调函数，处理接收到的帧
            callback(frame, userData);
        }
    }
#endif
}
