#include "Arb_Pack.h"
#include "CM_Convert.h"

/**
 * @brief 打包仲裁请求/应答帧
 * @return 成功返回固定报文长度26，入参非法或缓冲区不足返回0。
 */
CM_INT32 Area_Arb_Frame_Pack(OUT CM_UINT8* buf, IN CM_UINT32 buf_size,
    IN STRU_AREA_WITH_ARB_PACK_T* pack)
{
    CM_UINT32 index = 0u;

    if ((NULL == buf) || (NULL == pack) || (buf_size < AREA_ARB_FRAME_PACK_LEN))
    {
        return 0;
    }

    /* 按协议字段顺序写入；多字节整数统一使用大端转换函数。 */
    buf[index++] = pack->Len;
    buf[index++] = (CM_UINT8)pack->MsgType;
    CM_LongToChar(pack->ArbSN, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    CM_ShortToChar(pack->OutNet_ID, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT16);
    buf[index++] = pack->Board_ID;
    buf[index++] = pack->CPU_ID;
    buf[index++] = pack->ArbPayLoad;
    /* 预留区为字节数组，直接复制到报文缓冲区。 */
    (void)memcpy(&buf[index], pack->Reserver, AREA_ARB_RESERVER_LEN);
    index += AREA_ARB_RESERVER_LEN;
    CM_LongToChar(pack->CRC1, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    CM_LongToChar(pack->CRC2, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);

    return (CM_INT32)index;
}

/**
 * @brief 解包仲裁请求/应答帧
 * @note 入参非法或报文长度不足时不修改输出结构体。
 */
void Area_Arb_Frame_UnPack(OUT STRU_AREA_WITH_ARB_PACK_T* pack,
    IN CM_UINT8* buf, IN CM_UINT32 buf_len)
{
    CM_UINT32 index = 0u;

    if ((NULL == pack) || (NULL == buf) || (buf_len < AREA_ARB_FRAME_PACK_LEN))
    {
        return;
    }

    /* 按打包时相同的字段顺序读取，多字节整数按大端还原。 */
    pack->Len = buf[index++];
    pack->MsgType = (ENUM_AREA_ARB_MSG_TYPE_T)buf[index++];
    pack->ArbSN = CM_LongFromChar(&buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    pack->OutNet_ID = CM_ShortFromChar(&buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT16);
    pack->Board_ID = buf[index++];
    pack->CPU_ID = buf[index++];
    pack->ArbPayLoad = buf[index++];
    /* 预留区为字节数组，直接复制到输出结构体。 */
    (void)memcpy(pack->Reserver, &buf[index], AREA_ARB_RESERVER_LEN);
    index += AREA_ARB_RESERVER_LEN;
    pack->CRC1 = CM_LongFromChar(&buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    pack->CRC2 = CM_LongFromChar(&buf[index]);
}

/**
 * @brief 打包区域状态组播帧
 * @return 成功返回固定报文长度25，入参非法或缓冲区不足返回0。
 */
CM_INT32 Area_Arb_State_Multi_Pack(OUT CM_UINT8* buf, IN CM_UINT32 buf_size,
    IN STRU_AREA_WITH_ARB_STATE_MULTI_PACK_T* pack)
{
    CM_UINT32 index = 0u;

    if ((NULL == buf) || (NULL == pack) || (buf_size < AREA_ARB_STATE_MULTI_PACK_LEN))
    {
        return 0;
    }

    /* 按协议字段顺序写入；多字节整数统一使用大端转换函数。 */
    buf[index++] = pack->Len;
    buf[index++] = (CM_UINT8)pack->MsgType;
    CM_LongToChar(pack->SN, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    buf[index++] = pack->SrcID;
    buf[index++] = pack->StateArea;
    buf[index++] = pack->State2x;
    /* 预留区为字节数组，直接复制到报文缓冲区。 */
    (void)memcpy(&buf[index], pack->Reserver, AREA_ARB_RESERVER_LEN);
    index += AREA_ARB_RESERVER_LEN;
    CM_LongToChar(pack->CRC1, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    CM_LongToChar(pack->CRC2, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);

    return (CM_INT32)index;
}

/**
 * @brief 解包区域状态组播帧
 * @note 入参非法或报文长度不足时不修改输出结构体。
 */
void Area_Arb_State_Multi_UnPack(OUT STRU_AREA_WITH_ARB_STATE_MULTI_PACK_T* pack,
    IN CM_UINT8* buf, IN CM_UINT32 buf_len)
{
    CM_UINT32 index = 0u;

    if ((NULL == pack) || (NULL == buf) || (buf_len < AREA_ARB_STATE_MULTI_PACK_LEN))
    {
        return;
    }

    /* 按打包时相同的字段顺序读取，多字节整数按大端还原。 */
    pack->Len = buf[index++];
    pack->MsgType = (ENUM_AREA_ARB_MSG_TYPE_T)buf[index++];
    pack->SN = CM_LongFromChar(&buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    pack->SrcID = buf[index++];
    pack->StateArea = buf[index++];
    pack->State2x = buf[index++];
    /* 预留区为字节数组，直接复制到输出结构体。 */
    (void)memcpy(pack->Reserver, &buf[index], AREA_ARB_RESERVER_LEN);
    index += AREA_ARB_RESERVER_LEN;
    pack->CRC1 = CM_LongFromChar(&buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    pack->CRC2 = CM_LongFromChar(&buf[index]);
}

/**
 * @brief 打包地间状态请求/应答帧
 * @return 成功返回固定报文长度27，入参非法或缓冲区不足返回0。
 */
CM_INT32 Area_Arb_State_Pack(OUT CM_UINT8* buf, IN CM_UINT32 buf_size,
    IN STRU_AREA_WITH_ARB_STATE_PACK_T* pack)
{
    CM_UINT32 index = 0u;

    if ((NULL == buf) || (NULL == pack) || (buf_size < AREA_ARB_STATE_PACK_LEN))
    {
        return 0;
    }

    /* 按协议字段顺序写入；多字节整数统一使用大端转换函数。 */
    buf[index++] = pack->Len;
    buf[index++] = (CM_UINT8)pack->MsgType;
    CM_LongToChar(pack->SN, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    buf[index++] = pack->TimeSyncFlag;
    buf[index++] = pack->SrcID;
    buf[index++] = pack->DstID;
    buf[index++] = pack->StateArea;
    buf[index++] = pack->State2x;
    /* 预留区为字节数组，直接复制到报文缓冲区。 */
    (void)memcpy(&buf[index], pack->Reserver, AREA_ARB_RESERVER_LEN);
    index += AREA_ARB_RESERVER_LEN;
    CM_LongToChar(pack->CRC1, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    CM_LongToChar(pack->CRC2, &buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);

    return (CM_INT32)index;
}

/**
 * @brief 解包地间状态请求/应答帧
 * @note 入参非法或报文长度不足时不修改输出结构体。
 */
void Area_Arb_State_UnPack(OUT STRU_AREA_WITH_ARB_STATE_PACK_T* pack,
    IN CM_UINT8* buf, IN CM_UINT32 buf_len)
{
    CM_UINT32 index = 0u;

    if ((NULL == pack) || (NULL == buf) || (buf_len < AREA_ARB_STATE_PACK_LEN))
    {
        return;
    }

    /* 按打包时相同的字段顺序读取，多字节整数按大端还原。 */
    pack->Len = buf[index++];
    pack->MsgType = (ENUM_AREA_ARB_MSG_TYPE_T)buf[index++];
    pack->SN = CM_LongFromChar(&buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    pack->TimeSyncFlag = buf[index++];
    pack->SrcID = buf[index++];
    pack->DstID = buf[index++];
    pack->StateArea = buf[index++];
    pack->State2x = buf[index++];
    /* 预留区为字节数组，直接复制到输出结构体。 */
    (void)memcpy(pack->Reserver, &buf[index], AREA_ARB_RESERVER_LEN);
    index += AREA_ARB_RESERVER_LEN;
    pack->CRC1 = CM_LongFromChar(&buf[index]);
    index += (CM_UINT32)sizeof(CM_UINT32);
    pack->CRC2 = CM_LongFromChar(&buf[index]);
}

