#include "radio_ctrl/uart_handler.h"
#include "radio_ctrl/get_config.h"
#include <iostream>
#include <algorithm>
#include <rclcpp/rclcpp.hpp>
#include "sweeper_interfaces/msg/mc_ctrl.hpp"
#include "sweeper_interfaces/msg/can_frame.hpp"

namespace sweeperMsg = sweeper_interfaces::msg;

constexpr float DEG_PER_SEC_TO_RPM = 1.0f / 6.0f;
constexpr float GEAR_RATIO = 16.5f;
constexpr float DELTA_T = 0.02f; // 20ms

class SBUSNode : public rclcpp::Node
{
public:
    SBUSNode() : Node("sbus_node"), current_feedback_angle(0.0f)
    {
        if (load_config(config))
        {
            std::cout << "Serial Port: " << config.serial_port << "\n";
            std::cout << "Baudrate: " << config.baudrate << "\n";
            std::cout << "MCU RPM Max: " << config.mcu_rpm_max << "\n";
            std::cout << "EPS Angle Max: " << config.eps_angle_max << "\n";
        }

        // 发布控制指令消息的发布器
        pub_ = this->create_publisher<sweeperMsg::McCtrl>("radio_mc_ctrl", 10);

        // 订阅CAN反馈的回调函数
        can_sub_ = this->create_subscription<sweeperMsg::CanFrame>(
            "can_data", 10,
            std::bind(&SBUSNode::can_callback, this, std::placeholders::_1));

        // 初始化串口读取（读取遥控器数据）
        uart_handler_ = std::make_shared<UartHandler>(config.serial_port, config.baudrate);
        if (!uart_handler_->open_serial())
        {
            RCLCPP_ERROR(this->get_logger(), "Failed to open serial port!");
            return;
        }
        uart_handler_->start_reading(); // 启动串口后台读线程

        // 创建周期定时器（每20ms回调一次控制逻辑，50Hz）
        timer_ = this->create_wall_timer(
            std::chrono::milliseconds(20),
            std::bind(&SBUSNode::timer_callback, this));
    }

    ~SBUSNode()
    {
        if (uart_handler_)
        {
            uart_handler_->stop_reading();
        }
    }

private:
    // 定时器回调函数，用于周期性发布控制指令
    void timer_callback()
    {
        static int MCU_RPM_MAX = config.mcu_rpm_max;
        static float EPS_ANGLE_MAX = config.eps_angle_max;
        // static bool initialized = false; // 新增初始化标志

        bool data_safe = uart_handler_->get_data_safe(); // 获取数据安全性

        auto msg = sweeperMsg::McCtrl(); // 控制消息对象
        uint16_t ch_data[10];            // 各通道遥控数据

        if (data_safe) // 数据安全，进行数据解析并发布
        {
            // 赋值与打印
            for (int i = 0; i < 10; ++i)
            {
                ch_data[i] = uart_handler_->get_channel_value(i);
                // printf("ch[%d]:%d   ", i, ch_data[i]);
            }
            // printf("\n");

            uint16_t gear = ch_data[7];       // 挡位 最下1792，中间992，最上192
            uint16_t sweep = ch_data[6];      // 清扫 最上192，最下1792
            int16_t speed = ch_data[2] - 992; // 左边摇杆，最下192，中间992，最上1792 -> [-800,800]

            // 挡位选择
            if (gear == 192)
            {
                msg.gear = 1; // D挡
            }
            else if (gear == 992)
            {
                msg.gear = 0; // N挡
            }
            else if (gear == 1792)
            {
                msg.gear = 2; // R挡
            }

            // 油门 / 刹车逻辑
            if (speed < 0)
            {
                msg.brake = 1;
                msg.rpm = 0;
            }
            else
            {
                msg.brake = 0;
                msg.rpm = static_cast<uint16_t>(std::clamp(MCU_RPM_MAX * speed / 800, 0, MCU_RPM_MAX));
            }

            // 不清扫
            if (sweep == 1792)
            {
                msg.roll_brush_suction_direction = 0;
                msg.roll_brush_suction = 0;
                msg.side_brush = 0;
                msg.dust_shake = 0;
                msg.brush_deck_pusher = 0;
                msg.suction_squeeqee_pusher = 0;
                msg.water_spray = 0;
            }
            // 清扫
            else if (sweep == 192)
            {
                msg.roll_brush_suction_direction = 1;
                msg.roll_brush_suction = 100;
                msg.side_brush = 100;
                msg.dust_shake = 100;
                msg.brush_deck_pusher = 100;
                msg.suction_squeeqee_pusher = 100;
                msg.water_spray = 100;
            }

            // 转向逻辑
            float target_angle = (static_cast<float>(ch_data[0]) - 947) / 800 * EPS_ANGLE_MAX;

            // 角速度（度/秒）
            float angle_speed = fabs(target_angle - current_feedback_angle) / DELTA_T;

            // 电机转速（单位：rpm）
            float motor_rpm = angle_speed * DEG_PER_SEC_TO_RPM * GEAR_RATIO;

            // 限制电机转速到 [120, 1500] 范围，防止过小/过大
            uint16_t can_speed = std::clamp(
                static_cast<uint16_t>(motor_rpm),
                static_cast<uint16_t>(120),
                static_cast<uint16_t>(1500));

            msg.angle = target_angle;
            msg.angle_speed = can_speed;

            // 发布控制消息
            pub_->publish(msg);

            std::cout << "\n  刹车: " << (msg.brake ? "已刹车" : "未刹车")
                      << "\n  挡位: ";
            switch (msg.gear)
            {
            case 0:
                std::cout << "空挡";
                break;
            case 1:
                std::cout << "前进挡";
                break;
            case 2:
                std::cout << "后退挡";
                break;
            default:
                std::cout << "未知挡位(" << static_cast<int>(msg.gear) << ")";
                break;
            }
            std::cout << "\n  行走电机转速: " << static_cast<int>(msg.rpm) << " RPM"
                      << "\n  轮端转向角度: " << msg.angle << "°"
                      << "\n  清扫状态: " << (msg.roll_brush_suction_direction ? "正在清扫" : "未清扫")
                      << std::endl;
        }
        else
        {
            RCLCPP_INFO(this->get_logger(), "Waiting for radio control data...");
            return; // 下次循环，等待数据安全
        }
    }

    // CAN反馈回调函数（用于获取当前转向角度）
    void can_callback(const sweeperMsg::CanFrame::SharedPtr msg)
    {
        // 判断是否为转向反馈帧（ID=0x401，且数据长度大于5）
        if (msg->id == 0x401 && msg->dlc >= 5)
        {
            // 第3、4字节拼接为原始角度数据
            uint16_t raw_value = static_cast<uint16_t>((msg->data[3] << 8) | msg->data[4]);

            // 数据偏移：减去1024并除以5，得到角度（单位：度）
            current_feedback_angle = (raw_value - 1024) / 7.0f;
        }
    }

    // ROS2 发布/订阅/定时器/串口读取器
    rclcpp::Publisher<sweeperMsg::McCtrl>::SharedPtr pub_;
    rclcpp::Subscription<sweeperMsg::CanFrame>::SharedPtr can_sub_;
    rclcpp::TimerBase::SharedPtr timer_;
    std::shared_ptr<UartHandler> uart_handler_;

    float current_feedback_angle; // 当前反馈角度（从CAN中读取）
    RmoCtlConfig config;
};

int main(int argc, char *argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<SBUSNode>()); // 启动节点
    rclcpp::shutdown();
    return 0;
}