#ifndef AREA_PACK_H_
#define AREA_PACK_H_

#include "CM_Types.h"
#include "SFM_2x2.h"
#include "Area.h"

/* 各类报文在线路上的固定长度，不包含结构体对齐字节。 */
#define AREA_ARB_FRAME_PACK_LEN               (27u)
#define AREA_ARB_STATE_MULTI_PACK_LEN         (25u)
#define AREA_ARB_STATE_PACK_LEN               (27u)

#define AREA_ARB_RESERVER_LEN            (8u)

/**< 仲裁模式下，区域通信的消息类型 */
typedef enum
{
    ENUM_AREA_MSG_ARB_REQ = 0x01,    /**< 仲裁请求帧 */
    ENUM_AREA_MSG_ARB_ACK = 0x81,    /**< 仲裁应答帧 */

    ENUM_AREA_MSG_STATE_REQ = 0x02,  /**< 区域状态请求帧 */
    ENUM_AREA_MSG_STATE_ACK = 0x82,  /**< 区域状态应答帧 */

    ENUM_AREA_MSG_STATE_MULTI = 0x03, /**< 区域状态组播帧 */
}ENUM_AREA_ARB_MSG_TYPE_T;

/* 仲裁模式下，仲裁请求与回复的帧格式 */
typedef struct
{
    CM_UINT8 Len;                       /**< 数据包长度 */
    ENUM_AREA_ARB_MSG_TYPE_T MsgType;   /**< 消息类型 */
    CM_UINT32 ArbSN;                    /**< 仲裁请求/应答序列号 */
    CM_UINT16 OutNet_ID;                /**< 外网ID */
    CM_UINT8 Board_ID;                  /**< 板卡ID */
    CM_UINT8 CPU_ID;                    /**< CPUID */
    CM_UINT8 ArbPayLoad;                /**< 仲裁请求/回复的具体内容 */
    CM_UINT8 Reserver[AREA_ARB_RESERVER_LEN];               /**< 预留8字节 */
    CM_UINT32 CRC1;                     /**< CRC1 */
    CM_UINT32 CRC2;                     /**< CRC2 */
}STRU_AREA_WITH_ARB_PACK_T;

/* 仲裁模式下，组播状态帧格式 */
typedef struct
{
    CM_UINT8 Len;                       /**< 数据包长度 */
    ENUM_AREA_ARB_MSG_TYPE_T MsgType;   /**< 消息类型 */
    CM_UINT32 SN;                       /**< 消息SN号(周期号) */
    CM_UINT8 SrcID;                     /**< 源ID(板卡ID) */
    ENUM_AREA_STATE StateArea;                 /**< 区域状态 */
    ENUM_2x2_STATE_T State2x;                   /**< 2x状态 */
    CM_UINT8 Reserver[AREA_ARB_RESERVER_LEN];               /**< 预留8字节 */
    CM_UINT32 CRC1;                     /**< CRC1 */
    CM_UINT32 CRC2;                     /**< CRC2 */
}STRU_AREA_WITH_ARB_STATE_MULTI_PACK_T;

/**仲裁模式下，地间状态请求与回复帧格式 */
typedef struct
{
    CM_UINT8 Len;                       /**< 数据包长度 */
    ENUM_AREA_ARB_MSG_TYPE_T MsgType;   /**< 消息类型 */
    CM_UINT32 SN;                       /**< 消息SN号(周期号) */
    CM_UINT8 TimeSyncFlag;              /**< 校时标志(用于判断是否需要容忍接收) */
    CM_UINT8 SrcID;                     /**< 源ID(板卡ID) */
    CM_UINT8 DstID;                     /**< 目的ID(板卡ID) */
    ENUM_AREA_STATE StateArea;                 /**< 区域状态 */
    ENUM_2x2_STATE_T State2x;                   /**< 2x状态 */
    CM_UINT8 Reserver[AREA_ARB_RESERVER_LEN];               /**< 预留8字节 */
    CM_UINT32 CRC1;                     /**< CRC1 */
    CM_UINT32 CRC2;                     /**< CRC2 */   
}STRU_AREA_WITH_ARB_STATE_PACK_T;

/**
 * @brief 将仲裁请求结构体的内容写入缓冲区
 * @param pack 请求结构体
 * @param buf  缓冲区
 * @param buf_size 缓冲区大小
 * @return CM_INT32 写入的长度
 * @note 如果使用该打包函数，解包时也必须使用对应解包函数，避免因为结构体对齐出现问题
 */
CM_INT32 Area_Arb_Frame_Pack(OUT CM_UINT8* buf, IN CM_UINT32 buf_size, IN STRU_AREA_WITH_ARB_PACK_T* pack);

/**
 * @brief 将缓冲区写入仲裁请求结构体的内容
 * @param pack 请求结构体
 * @param buf  缓冲区
 * @param buf_len 缓冲区大小
 * @return CM_INT32 写入的长度
 * @note 仅对打包函数处理后的数据进行解包
 */
void Area_Arb_Frame_UnPack(OUT STRU_AREA_WITH_ARB_PACK_T* pack, IN CM_UINT8* buf, IN CM_UINT32 buf_len);

/**
 * @brief 将组播状态帧结构体的内容写入缓冲区
 * @param pack 请求结构体
 * @param buf  缓冲区
 * @param buf_size 缓冲区大小
 * @return CM_INT32 写入的长度
 * @note 如果使用该打包函数，解包时也必须使用对应解包函数，避免因为结构体对齐出现问题
 */
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);

/**
 * @brief 将缓冲区写入组播状态帧结构体
 * @param pack 请求结构体
 * @param buf  缓冲区
 * @param buf_len 缓冲区大小
 * @return CM_INT32 写入的长度
 * @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);

/**
 * @brief 将地间状态请求结构体的内容写入缓冲区
 * @param pack 请求结构体
 * @param buf  缓冲区
 * @param buf_size 缓冲区大小
 * @return CM_INT32 写入的长度
 * @note 如果使用该打包函数，解包时也必须使用对应解包函数，避免因为结构体对齐出现问题
 */
CM_INT32 Area_Arb_State_Pack(OUT CM_UINT8* buf, IN CM_UINT32 buf_size, IN STRU_AREA_WITH_ARB_STATE_PACK_T* pack);

/**
 * @brief 将缓冲区写入地间状态请求结构体
 * @param pack 请求结构体
 * @param buf  缓冲区
 * @param buf_len 缓冲区大小
 * @return CM_INT32 写入的长度
 * @note 仅对打包函数处理后的数据进行解包
 */
void Area_Arb_State_UnPack(OUT STRU_AREA_WITH_ARB_STATE_PACK_T* pack, IN CM_UINT8* buf, IN CM_UINT32 buf_len);

#endif
