#include "protocol.h"
#include "string.h"
#include "utils.h"

int protocol_pack_frame(
    uint16_t slave_addr,
    uint8_t command,const 
    uint8_t *payload,
    uint16_t payload_len,
    uint8_t *buffer,uint16_t buffer_size,
    uint16_t *packed_len)
{

    // 构建基础帧头

    buffer[0] = PROTOCOL_HEAD & 0xFF;  
    buffer[1] = (PROTOCOL_HEAD >> 8) & 0xFF;
    buffer[2] = slave_addr & 0xFF;  
    buffer[3] = (slave_addr >> 8) & 0xFF;
    
    buffer[4] = command;
    
    buffer[5] = payload_len & 0xFF;  
    buffer[6] = (payload_len >> 8) & 0xFF;

    // 复制有效载荷（保持小端格式）
    if (payload_len > 0 && payload != NULL) {
        memcpy(buffer + PROTOCOL_FRAME_HEAD_SIZE , payload, payload_len);
    }

     // 设置实际长度
    int fram_len = PROTOCOL_FRAME_MIN_SIZE + payload_len;
    
    
    // 计算CRC（覆盖地址、命令、长度和有效载荷）
    uint16_t crc = 0xFFFF;
    
    crc = modbus_crc16(buffer,fram_len -2);
    
    // 写入CRC（保持小端格式）

    buffer[fram_len-2] = (uint8_t)(crc & 0xFF);
    buffer[fram_len-1] = (uint8_t)(crc >> 8);

    *packed_len =fram_len;
    
    return PROTOCOL_SUCCESS;
    
}

int protocol_unpack_frame(
    const uint8_t *frame,
    uint16_t frame_len,
    uint16_t *slave_addr,
    uint8_t *command,
    uint8_t *payload,
    uint16_t *payload_len
) {
    // 参数校验
    if (frame == NULL || slave_addr == NULL || command == NULL || payload_len == NULL) {
        return PROTOCOL_ERR_INVALID_PARAM;
    }
    if (frame_len > 64) {
        return PROTOCOL_ERR_BUFFER_OVERFLOW;
    }

    if (frame_len < PROTOCOL_FRAME_MIN_SIZE) {
        return PROTOCOL_ERR_INVALID_PARAM;
    }

    // 帧头校验
    uint16_t header = (frame[0] | frame[1] <<8);
    
    if (header != PROTOCOL_HEAD) {
        
        return PROTOCOL_ERR_INVALID_PARAM;
    }

    // 基础字段解析
    *slave_addr  =   (frame[2] | frame[3] << 8);
    
    
    *command     =    frame[4];
    
    
    *payload_len =   (frame[5] | frame[6] << 8);
    
    // 数据完整性校验
    if (*payload_len > (frame_len - PROTOCOL_FRAME_MIN_SIZE)) {
        
        return PROTOCOL_ERR_BUFFER_OVERFLOW;
    }

    int frame_size = *payload_len + 9;
    
    uint16_t calc_crc =0xffff;
    
    calc_crc =  modbus_crc16((uint8_t *)frame, frame_size -2 );

    // 校验CRC（保持小端格式）
    union{
    
        uint16_t value;
        struct{
          uint8_t  crcl;
          uint8_t  crch;
        }bytes;
        
    }crc_data;
    
    crc_data.bytes.crcl  =(frame[frame_size - 2] ) ;
    crc_data.bytes.crch  =(frame[frame_size - 1] ) ;
    
    if (calc_crc != crc_data.value) {
        return PROTOCOL_ERR_CRC;
    }

    // 复制有效载荷（保持小端格式）
    if (*payload_len > 0 && payload != NULL) {
        memcpy(payload, frame + PROTOCOL_FRAME_HEAD_SIZE, *payload_len);
    }

    return PROTOCOL_SUCCESS;
}
