#ifndef CAN_STRUCT_H
#define CAN_STRUCT_H

#include <cstdint>
#include <array>
#include <string.h>
#include "can_driver.h"

#pragma pack(push, 1) // 禁止结构体补齐，确保8字节紧密排列

union can_MCU_cmd_union
{
    struct
    {
        // Byte 0
        uint8_t brake : 2;
        uint8_t gear : 2;
        uint8_t reserve1 : 1;
        uint8_t mode : 2;
        uint8_t enabled : 1;

        // Byte 1-2
        uint8_t reserve2;
        uint8_t reserve3;

        // Byte 3-4
        uint8_t rpm_h;
        uint8_t rpm_l;

        // Byte 5-6
        uint8_t brakeTime_h;
        uint8_t brakeTime_l;

        // Byte 7
        uint8_t checksum;
    } fields;

    uint8_t bytes[8];
};

union can_EPS_cmd_union
{
    struct
    {
        uint8_t control_mode;  // 控制方式
        uint8_t reserve1;      // 保留
        uint8_t reserve2;      // 保留
        uint8_t angle_h;       // 角度高位
        uint8_t angle_l;       // 角度低位
        uint8_t center_cmd;    // 角度对中指令
        uint8_t angular_speed; // 角速度控制
        uint8_t checksum;      // 异或校验
    } fields;

    uint8_t bytes[8];
};

#pragma pack(pop)

struct can_MCU_cmd
{
    can_MCU_cmd_union data;

    static constexpr uint32_t CMD_ID = 0x1A1;
    static constexpr bool EXT_FLAG = false;
    static constexpr bool RTR_FLAG = false;

    // 构造函数自动初始化常量
    can_MCU_cmd()
    {
        memset(&data, 0, sizeof(data));
        data.fields.mode = 1;
        data.fields.reserve1 = 0;
        data.fields.reserve2 = 0;
        data.fields.reserve3 = 0;
    }

    void setEnabled(bool en)
    {
        data.fields.enabled = en ? 1 : 0;
    }

    void setGear(uint8_t gear)
    {
        data.fields.gear = gear & 0x03;
    }

    void setBrake(uint8_t brake)
    {
        data.fields.brake = brake & 0x03;
    }

    void setRPM(uint16_t rpm)
    {
        data.fields.rpm_h = (rpm >> 8) & 0xFF;
        data.fields.rpm_l = rpm & 0xFF;
    }

    void setBrakeTime(uint16_t time_ms)
    {
        data.fields.brakeTime_h = (time_ms >> 8) & 0xFF;
        data.fields.brakeTime_l = time_ms & 0xFF;
    }

    void pack()
    {
        // 计算校验：Byte0 ~ Byte6
        uint8_t sum = 0;
        for (int i = 0; i < 7; ++i)
        {
            sum += data.bytes[i];
        }
        data.fields.checksum = ~sum;
    }

    CANFrame toFrame() const
    {
        CANFrame frame;
        frame.id = CMD_ID;
        memcpy(frame.data, data.bytes, 8);
        frame.dlc = 8;
        frame.ext = EXT_FLAG;
        frame.rtr = RTR_FLAG;
        return frame;
    }
};

struct can_EPS_cmd
{
    can_EPS_cmd_union data;

    static constexpr uint32_t CMD_ID = 0x469;
    static constexpr bool EXT_FLAG = false;
    static constexpr bool RTR_FLAG = false;

    can_EPS_cmd()
    {
        memset(&data, 0, sizeof(data));
    }

    void setControlMode(uint8_t mode)
    {
        data.fields.control_mode = mode;
    }

    void setAngle(int16_t angle)
    {
        int16_t raw = angle + 1024; // angle公式：receive[3]*256+receive[4]-1024
        data.fields.angle_h = (raw >> 8) & 0xFF;
        data.fields.angle_l = raw & 0xFF;
    }

    void setCenterCmd(uint8_t cmd)
    {
        data.fields.center_cmd = cmd;
    }

    void setAngularSpeed(uint16_t angle_speed)
    {
        uint8_t value = angle_speed / 6;
        if (value < 20)
            value = 20;
        else if (value > 250)
            value = 250;
        data.fields.angular_speed = value;
    }

    void pack()
    {
        // 计算校验：Byte0 ~ Byte6的异或
        uint8_t xor_sum = 0;
        for (int i = 0; i < 7; ++i)
        {
            xor_sum ^= data.bytes[i];
        }
        data.fields.checksum = xor_sum;
    }

    CANFrame toFrame() const
    {
        CANFrame frame;
        frame.id = CMD_ID;
        memcpy(frame.data, data.bytes, 8);
        frame.dlc = 8;
        frame.ext = EXT_FLAG;
        frame.rtr = RTR_FLAG;
        return frame;
    }
};

struct can_VCU_out1_cmd
{
    static constexpr uint32_t CMD_ID = 0x18f21117;
    static constexpr bool EXT_FLAG = true;
    static constexpr bool RTR_FLAG = false;

    union Byte3
    {
        struct
        {
            uint8_t night_light : 4; // 低 4 位（夜行灯等级）
            uint8_t reserved : 3;    // 保留位
            uint8_t leftLight : 1;   // 左转灯
        } bits;
        uint8_t raw = 0;
    };

    uint8_t data[8]{};

    Byte3 &byte3()
    {
        return *reinterpret_cast<Byte3 *>(&data[3]);
    }

    void setLeftLight(bool on)
    {
        byte3().bits.leftLight = on ? 1 : 0;
    }

    // 传入百分比（0~100），按每10%一级计算
    void setNightLightPercent(uint8_t percent)
    {
        if (percent > 100)
            percent = 100;
        uint8_t level = percent / 10; // 0–10
        byte3().bits.night_light = level;
    }

    // 传入布尔值，true = 100%，false = 0%
    void setNightLightPercent(bool on)
    {
        byte3().bits.night_light = on ? 0x0A : 0x00;
    }

    CANFrame toFrame() const
    {
        CANFrame frame;
        frame.id = CMD_ID;
        std::copy(std::begin(data), std::end(data), frame.data);
        frame.dlc = 8;
        frame.ext = EXT_FLAG;
        frame.rtr = RTR_FLAG;
        return frame;
    }
};

struct can_VCU_out2_cmd
{
    static constexpr uint32_t CMD_ID = 0x18fa1117;
    static constexpr bool EXT_FLAG = true;
    static constexpr bool RTR_FLAG = false;

    union Byte0
    {
        struct
        {
            uint8_t right_light : 1; // 右转灯
            uint8_t brake_light : 1; // 刹车灯
            uint8_t reserved0 : 6;   // 保留位
        } bits;
        uint8_t raw = 0;
    };

    union Byte1
    {
        struct
        {
            uint8_t reserved1 : 5;       // 保留位
            uint8_t main_brush_lift : 1; // 主刷推杆
            uint8_t reserved2 : 1;       // 保留位
            uint8_t headlight : 1;       // 大灯
        } bits;
        uint8_t raw = 0;
    };

    union Byte3
    {
        struct
        {
            uint8_t edge_brush_lift : 1; // 边刷推杆
            uint8_t reserved3 : 1;       // 保留位
            uint8_t spray : 1;           // 喷水
            uint8_t reserved4 : 1;       // 保留位
            uint8_t dust_shake : 1;      //  振尘
            uint8_t vacuum : 1;          // 吸尘
            uint8_t mud_flap : 1;        // 挡皮
            uint8_t reserved5 : 1;       // 保留位
        } bits;
        uint8_t raw = 0;
    };

    uint8_t data[8]{};

    Byte0 &byte0() { return *reinterpret_cast<Byte0 *>(&data[0]); }
    Byte1 &byte1() { return *reinterpret_cast<Byte1 *>(&data[1]); }
    Byte3 &byte3() { return *reinterpret_cast<Byte3 *>(&data[3]); }

    // === Byte0 控制 ===
    void setRightLight(bool on)
    {
        byte0().bits.right_light = on ? 1 : 0;
    }

    void setBrakeLight(bool on)
    {
        byte0().bits.brake_light = on ? 1 : 0;
    }

    // === Byte1 控制 ===
    void setMainBrushLift(bool on)
    {
        byte1().bits.main_brush_lift = on ? 1 : 0;
    }

    void setHeadlight(bool on)
    {
        byte1().bits.headlight = on ? 1 : 0;
    }

    // === Byte3 控制 ===
    void setEdgeBrushLift(bool on)
    {
        byte3().bits.edge_brush_lift = on ? 1 : 0;
    }

    void setSpray(bool on)
    {
        byte3().bits.spray = on ? 1 : 0;
    }

    void setDustShake(bool on)
    {
        byte3().bits.dust_shake = on ? 1 : 0;
    }

    void setVacuum(bool on)
    {
        byte3().bits.vacuum = on ? 1 : 0;
    }

    void setMudFlap(bool on)
    {
        byte3().bits.mud_flap = on ? 1 : 0;
    }

    CANFrame toFrame() const
    {
        CANFrame frame;
        frame.id = CMD_ID;
        std::copy(std::begin(data), std::end(data), frame.data);
        frame.dlc = 8;
        frame.ext = EXT_FLAG;
        frame.rtr = RTR_FLAG;
        return frame;
    }
};

struct can_main_Brush_cmd
{
    static constexpr uint32_t CMD_ID = 0x0cee36ef;
    static constexpr bool EXT_FLAG = true;
    static constexpr bool RTR_FLAG = false;

    union Byte0
    {
        struct
        {
            uint8_t right_motor_pwm : 8;
        } bits;
        uint8_t raw = 0;
    };

    union Byte1
    {
        struct
        {
            uint8_t left_motor_pwm : 8;
        } bits;
        uint8_t raw = 0;
    };

    union Byte7
    {
        struct
        {
            uint8_t can_enabled : 8;
        } bits;
        uint8_t raw = 0;
    };

    uint8_t data[8]{};

    can_main_Brush_cmd()
    {
        data[3] = 1; // 固定字节初始化
    }

    Byte0 &byte0() { return *reinterpret_cast<Byte0 *>(&data[0]); }
    Byte1 &byte1() { return *reinterpret_cast<Byte1 *>(&data[1]); }
    Byte7 &byte7() { return *reinterpret_cast<Byte7 *>(&data[7]); }

    // === Byte0,1 控制 ===
    void setBrushPwm(uint8_t pwm)
    {
        if (pwm > 100)
        {
            pwm = 100;
        }
        byte0().bits.right_motor_pwm = pwm;
        byte1().bits.left_motor_pwm = pwm;
    }

    // === Byte7 控制 ===
    void setBrushEnable(bool on)
    {
        byte7().bits.can_enabled = on ? 1 : 0;
    }

    CANFrame toFrame() const
    {
        CANFrame frame;
        frame.id = CMD_ID;
        std::copy(std::begin(data), std::end(data), frame.data);
        frame.dlc = 8;
        frame.ext = EXT_FLAG;
        frame.rtr = RTR_FLAG;
        return frame;
    }
};

struct can_edge_Brush_cmd
{
    static constexpr uint32_t CMD_ID = 0x0cee26ef;
    static constexpr bool EXT_FLAG = true;
    static constexpr bool RTR_FLAG = false;

    union Byte0
    {
        struct
        {
            uint8_t right_motor_pwm : 8;
        } bits;
        uint8_t raw = 0;
    };

    union Byte1
    {
        struct
        {
            uint8_t left_motor_pwm : 8;
        } bits;
        uint8_t raw = 0;
    };

    union Byte7
    {
        struct
        {
            uint8_t can_enabled : 8;
        } bits;
        uint8_t raw = 0;
    };

    uint8_t data[8]{};

    can_edge_Brush_cmd()
    {
        data[3] = 1; // 固定字节初始化
    }

    Byte0 &byte0() { return *reinterpret_cast<Byte0 *>(&data[0]); }
    Byte1 &byte1() { return *reinterpret_cast<Byte1 *>(&data[1]); }
    Byte7 &byte7() { return *reinterpret_cast<Byte7 *>(&data[7]); }

    // === Byte0,1 控制 ===
    void setBrushPwm(uint8_t pwm)
    {
        if (pwm > 100)
        {
            pwm = 100;
        }
        byte0().bits.right_motor_pwm = pwm;
        byte1().bits.left_motor_pwm = pwm;
    }

    // === Byte7 控制 ===
    void setBrushEnable(bool on)
    {
        byte7().bits.can_enabled = on ? 1 : 0;
    }

    CANFrame toFrame() const
    {
        CANFrame frame;
        frame.id = CMD_ID;
        std::copy(std::begin(data), std::end(data), frame.data);
        frame.dlc = 8;
        frame.ext = EXT_FLAG;
        frame.rtr = RTR_FLAG;
        return frame;
    }
};

extern can_MCU_cmd mcu_cmd;
extern can_EPS_cmd eps_cmd;
extern can_VCU_out1_cmd vcu1_cmd;
extern can_VCU_out2_cmd vcu2_cmd;
extern can_main_Brush_cmd main_brush_cmd;
extern can_edge_Brush_cmd edge_brush_cmd;

#endif
