/*
 * Balance Chassis Module
 */

/* Includes ----------------------------------------------------------------- */
#include "module/balance_chassis.h"
#include "bsp/can.h"
#include "bsp/time.h"
#include "component/user_math.h"
#include "device/motor_lk.h"
#include "module/config.h"
#include <string.h>
#include <math.h>

/* Private typedef ---------------------------------------------------------- */
/* Private define ----------------------------------------------------------- */
#define CAN_CMD_ENABLE_ID      121  // 使能命令ID
#define CAN_CMD_JOINT_ID       122  // 关节控制命令ID  
#define CAN_CMD_WHEEL_LEFT_ID  0x128  // 左轮控制命令ID
#define CAN_CMD_WHEEL_RIGHT_ID 0x129  // 右轮控制命令ID

#define CAN_FEEDBACK_JOINT_BASE_ID 124  // 关节反馈基础ID (124-127)
#define CAN_FEEDBACK_WHEEL_LEFT_ID 130  // 左轮反馈ID
#define CAN_FEEDBACK_WHEEL_RIGHT_ID 131 // 右轮反馈ID

/* Private macro ------------------------------------------------------------ */
#define CMD_TIMEOUT_MS 50  // 50ms超时时间，允许控制频率在10-20Hz之间

/* Private variables -------------------------------------------------------- */
static bool joint_command_received = false;
static bool wheel_command_received[2] = {false, false};

// 超时管理 - 防止控制频率不同导致的控制/relax交替
static uint32_t joint_last_cmd_time = 0;
static uint32_t wheel_last_cmd_time[2] = {0, 0};

/* Private function --------------------------------------------------------- */

/**
 * @brief 检查并处理CAN控制命令
 * @param chassis 底盘实例
 * @return 成功返回DEVICE_OK
 */
static int8_t Chassis_ProcessCANCommands(Chassis_t *chassis) {
    BSP_CAN_Message_t rx_msg;
    joint_command_received = false;
    wheel_command_received[0] = false;
    wheel_command_received[1] = false;
  
        // 检查ID 128 - 左轮控制命令 (与电机发送格式一致)
    if (BSP_CAN_GetMessage(BSP_CAN_1, CAN_CMD_WHEEL_LEFT_ID, &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
        wheel_command_received[0] = true;
        wheel_last_cmd_time[0] = BSP_TIME_Get_ms(); // 更新左轮命令时间戳
        float left_out = (float)((int16_t)(rx_msg.data[4] | (rx_msg.data[5] << 8))) / 2048.0f;
        chassis->output.wheel[0] = left_out;
        MOTOR_LK_SetOutput(&chassis->param.wheel_param[0], left_out);

    }
    
    // 检查ID 129 - 右轮控制命令 (与电机发送格式一致) 
    if (BSP_CAN_GetMessage(BSP_CAN_1, CAN_CMD_WHEEL_RIGHT_ID, &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
        wheel_command_received[1] = true;
        wheel_last_cmd_time[1] = BSP_TIME_Get_ms(); // 更新右轮命令时间戳
        float right_out = (float)((int16_t)(rx_msg.data[4] | (rx_msg.data[5] << 8))) / 2048.0f;
        chassis->output.wheel[1] = right_out;
        MOTOR_LK_SetOutput(&chassis->param.wheel_param[1], right_out);
    }

    BSP_TIME_Delay_ms(1); // 短暂延时，避免总线冲突


    // 检查ID 121 - 使能4个关节电机
    if (BSP_CAN_GetMessage(BSP_CAN_1, CAN_CMD_ENABLE_ID, &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
        joint_command_received = true;
        for (int i = 0; i < 4; i++) {
            MOTOR_LZ_Enable(&chassis->param.joint_param[i]);
        }
    }
    
    // 检查ID 122 - 运控模式控制4个关节电机
    if (BSP_CAN_GetMessage(BSP_CAN_1, CAN_CMD_JOINT_ID, &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
        joint_command_received = true;
        joint_last_cmd_time = BSP_TIME_Get_ms(); // 更新关节命令时间戳

        
        
        // 8字节数据分别是4个电机的力矩 (每个电机2字节，有符号整数，精度0.01 Nm)
        for (int i = 0; i < 4; i++) {
            int16_t torque_raw;
            memcpy(&torque_raw, &rx_msg.data[i * 2], sizeof(int16_t));
            float torque = (float)torque_raw / 100.0f; // 转换为浮点数力矩值
            chassis->output.joint[i] = torque;
            // 使用运控模式控制电机，只设置力矩，其他参数为0
            MOTOR_LZ_MotionParam_t motion_param = {
                .target_angle = 0.0f,
                .target_velocity = 0.0f,
                .kp = 0.0f,
                .kd = 0.0f,
                .torque = torque
            };
            MOTOR_LZ_MotionControl(&chassis->param.joint_param[i], &motion_param);
        }
    }

    return DEVICE_OK;
}

/**
 * @brief 发送关节电机反馈数据
 * @param chassis 底盘实例  
 * @return 成功返回DEVICE_OK
 */
static int8_t Chassis_SendJointFeedback(Chassis_t *chassis) {
    // 发送4个关节电机的反馈数据，ID分别为124、125、126、127
    for (int i = 0; i < 4; i++) {
        MOTOR_LZ_t* motor = MOTOR_LZ_GetMotor(&chassis->param.joint_param[i]);
        if (motor != NULL) {
            BSP_CAN_StdDataFrame_t motor_frame = {
                .id = CAN_FEEDBACK_JOINT_BASE_ID + i,  // ID: 124, 125, 126, 127
                .dlc = 8,
                .data = {0}
            };
            
            // 数据重构：转矩电流(2字节) + 位置(3字节) + 速度(3字节) = 8字节
            // 转矩电流 - 转换为16位整数 (精度0.01 Nm)
            int16_t torque_int = (int16_t)(motor->lz_feedback.current_torque * 100);
            memcpy(&motor_frame.data[0], &torque_int, sizeof(int16_t));
            
            // 位置 - 转换为24位整数，使用3字节 (精度0.0001 rad)
            int32_t angle_int = (int32_t)(motor->lz_feedback.current_angle * 10000) & 0xFFFFFF;
            motor_frame.data[2] = (angle_int >> 16) & 0xFF;
            motor_frame.data[3] = (angle_int >> 8) & 0xFF;
            motor_frame.data[4] = angle_int & 0xFF;
            
            // 速度 - 转换为24位整数，使用3字节 (精度0.001 rad/s)
            int32_t velocity_int = (int32_t)(motor->lz_feedback.current_velocity * 1000) & 0xFFFFFF;
            motor_frame.data[5] = (velocity_int >> 16) & 0xFF;
            motor_frame.data[6] = (velocity_int >> 8) & 0xFF;
            motor_frame.data[7] = velocity_int & 0xFF;
            
            BSP_CAN_TransmitStdDataFrame(BSP_CAN_1, &motor_frame);
        }
    }
    
    return DEVICE_OK;
}

/**
 * @brief 发送轮子电机反馈数据
 * @param chassis 底盘实例
 * @return 成功返回DEVICE_OK  
 */
static int8_t Chassis_SendWheelFeedback(Chassis_t *chassis) {
    // 发送2个轮子电机的反馈数据，ID分别为130、131
    for (int i = 0; i < 2; i++) {
        MOTOR_LK_t* motor = MOTOR_LK_GetMotor(&chassis->param.wheel_param[i]);
        if (motor != NULL) {
            BSP_CAN_StdDataFrame_t wheel_frame = {
                .id = CAN_FEEDBACK_WHEEL_LEFT_ID + i,  // ID: 130, 131
                .dlc = 8,
                .data = {0}
            };
            
            // 使用LK电机的标准反馈格式
            // 角度(2字节) + 速度(2字节) + 力矩电流(2字节) + 编码器(2字节)
            
            // 角度 - 转换为16位整数 (精度0.01度)
            int16_t angle_int = (int16_t)(motor->motor.feedback.rotor_abs_angle * 180.0f / M_PI * 100);
            wheel_frame.data[0] = (angle_int >> 8) & 0xFF;
            wheel_frame.data[1] = angle_int & 0xFF;
            
            // 速度 - 转换为16位整数 (精度1dps)  
            int16_t speed_int = (int16_t)(motor->motor.feedback.rotor_speed);
            wheel_frame.data[2] = (speed_int >> 8) & 0xFF;
            wheel_frame.data[3] = speed_int & 0xFF;
            
            // 力矩电流 - 转换为16位整数
            int16_t current_int = (int16_t)(motor->motor.feedback.torque_current);
            wheel_frame.data[4] = (current_int >> 8) & 0xFF;
            wheel_frame.data[5] = current_int & 0xFF;
            
            // 编码器值 - 直接使用角度值作为编码器
            uint16_t encoder = (uint16_t)(motor->motor.feedback.rotor_abs_angle / (2 * M_PI) * 65535);
            wheel_frame.data[6] = (encoder >> 8) & 0xFF;
            wheel_frame.data[7] = encoder & 0xFF;
            
            BSP_CAN_TransmitStdDataFrame(BSP_CAN_1, &wheel_frame);
        }
    }
    
    return DEVICE_OK;
}

/* Exported functions ------------------------------------------------------- */

/**
 * @brief 底盘初始化
 * @param chassis 底盘实例
 * @param param 底盘参数  
 * @return 成功返回DEVICE_OK
 */
int8_t Chassis_Init(Chassis_t *chassis, Chassis_Param_t *param) {
    if (chassis == NULL || param == NULL) {
        return DEVICE_ERR_NULL;
    }
    
    // 复制参数
    memcpy(&chassis->param, param, sizeof(Chassis_Param_t));
    
    // 初始化CAN
    BSP_CAN_Init();
    
    // 初始化电机驱动
    MOTOR_LZ_Init();
    
    // 注册关节电机
    for (int i = 0; i < 4; i++) {
        if (MOTOR_LZ_Register(&chassis->param.joint_param[i]) != DEVICE_OK) {
            return DEVICE_ERR;
        }
    }
    
    // 注册轮子电机
    for (int i = 0; i < 2; i++) {
        if (MOTOR_LK_Register(&chassis->param.wheel_param[i]) != DEVICE_OK) {
            return DEVICE_ERR;
        }
    }
    
    // 注册CAN接收ID
    BSP_CAN_RegisterId(BSP_CAN_1, CAN_CMD_ENABLE_ID, 0);      // 使能命令
    BSP_CAN_RegisterId(BSP_CAN_1, CAN_CMD_JOINT_ID, 0);       // 关节控制命令
    BSP_CAN_RegisterId(BSP_CAN_1, CAN_CMD_WHEEL_LEFT_ID, 0);  // 左轮控制命令
    BSP_CAN_RegisterId(BSP_CAN_1, CAN_CMD_WHEEL_RIGHT_ID, 0); // 右轮控制命令
    
    return DEVICE_OK;
}

/**
 * @brief 更新底盘数据
 * @param chassis 底盘实例
 * @return 成功返回DEVICE_OK
 */
int8_t Chassis_Update(Chassis_t *chassis) {
    if (chassis == NULL) {
        return DEVICE_ERR_NULL;
    }
    
    // 更新所有电机数据
    MOTOR_LZ_UpdateAll();
    MOTOR_LK_UpdateAll();
    
    // 更新反馈数据
    for (int i = 0; i < 4; i++) {
        MOTOR_LZ_t* joint_motor = MOTOR_LZ_GetMotor(&chassis->param.joint_param[i]);
        if (joint_motor != NULL) {
            chassis->data.joint[i] = joint_motor->motor.feedback;
        }
    }
    
    for (int i = 0; i < 2; i++) {
        MOTOR_LK_t* wheel_motor = MOTOR_LK_GetMotor(&chassis->param.wheel_param[i]);
        if (wheel_motor != NULL) {
            chassis->data.wheel[i] = wheel_motor->motor.feedback;
        }
    }
    
    return DEVICE_OK;
}

/**
 * @brief 使能底盘
 * @param chassis 底盘实例
 * @return 成功返回DEVICE_OK
 */
int8_t Chassis_Enable(Chassis_t *chassis) {
    if (chassis == NULL) {
        return DEVICE_ERR_NULL;
    }
    
    // 使能关节电机
    for (int i = 0; i < 4; i++) {
        MOTOR_LZ_Enable(&chassis->param.joint_param[i]);
    }
    
    // 开启轮子电机
    for (int i = 0; i < 2; i++) {
        MOTOR_LK_MotorOn(&chassis->param.wheel_param[i]);
    }
    
    return DEVICE_OK;
}

/**
 * @brief 底盘松弛
 * @param chassis 底盘实例
 * @return 成功返回DEVICE_OK
 */
int8_t Chassis_Relax(Chassis_t *chassis) {
    if (chassis == NULL) {
        return DEVICE_ERR_NULL;
    }
    
    // 关节电机松弛
    for (int i = 0; i < 4; i++) {
        MOTOR_LZ_Relax(&chassis->param.joint_param[i]);
    }
    
    // 轮子电机松弛
    for (int i = 0; i < 2; i++) {
        MOTOR_LK_Relax(&chassis->param.wheel_param[i]);
    }
    
    return DEVICE_OK;
}

/**
 * @brief 底盘控制处理
 * @param chassis 底盘实例
 * @return 成功返回DEVICE_OK
 */
int8_t Chassis_Ctrl(Chassis_t *chassis) {
    if (chassis == NULL) {
        return DEVICE_ERR_NULL;
    }
    
    // 处理CAN控制命令
    Chassis_ProcessCANCommands(chassis);
    
    uint32_t current_time = BSP_TIME_Get_ms();
    
    // 关节电机超时检查 - 只有在超时时才执行relax
    if (!joint_command_received && 
        (current_time - joint_last_cmd_time) > CMD_TIMEOUT_MS) {
        for (int i = 0; i < 4; i++) {
            MOTOR_LZ_Relax(&chassis->param.joint_param[i]);

            chassis->output.joint[i] = 0.0f; // 松弛时输出力矩设为0
        }
    }
    
    // 轮子电机超时检查 - 只有在超时时才执行relax
    for (int i = 0; i < 2; i++) {
        if (!wheel_command_received[i] && 
            (current_time - wheel_last_cmd_time[i]) > CMD_TIMEOUT_MS) {
            MOTOR_LK_Relax(&chassis->param.wheel_param[i]);

            chassis->output.wheel[i] = 0.0f; // 松弛时输出设为0
        }
    }
    
    // 发送反馈数据
    Chassis_SendJointFeedback(chassis);
    Chassis_SendWheelFeedback(chassis);
    
    return DEVICE_OK;
}
