/**
 * @file    icp67.h
 * @brief   ICP67 协议库内部头文件 — TI/COT 常量、ASDU 帧结构、内部 API
 */

#ifndef _ICP67_H_
#define _ICP67_H_

#include "myIcp67.h"

#ifdef __cplusplus
extern "C" {
#endif

/* =========================== 设备类型 =========================== */

typedef enum
{
	ENUM_DEV_TYPE_MAINTENANCE = 1,  /**< 维护软件 */
	ENUM_DEV_TYPE_SYS          = 2,  /**< 主板 */
	ENUM_DEV_TYPE_SAMPL        = 3,  /**< 采样板 */
	ENUM_DEV_TYPE_LCD          = 4,  /**< LCD屏 */
}enum_dev_type;

/* =========================== 方向定义 =========================== */

typedef enum
{
	ENUM_DIR_SLAVE  = 0,  /**< 从动站 */
	ENUM_DIR_MASTER = 1,  /**< 启动站 */
}enum_dir;

/* =========================== 类型标识 (TI) =========================== */

#define TI_1   (1)    /**< 读独立编码参数 */
#define TI_2   (2)    /**< 写独立编码参数 */
#define TI_3   (3)    /**< 读自定义组合编码参数 [点表，校准数据] */
#define TI_4   (4)    /**< 写自定义组合编码参数 [点表，校准数据] */
#define TI_5   (5)    /**< 终端时间 */
#define TI_6   (6)    /**< 终端状态读取 [查询相关自检信息，版本号] */
#define TI_9   (9)    /**< 升级 */
#define TI_11  (11)   /**< 文件操作 [文件读写，升级时使用文件流程] */
#define TI_30  (30)   /**< 录波文件压缩 */
#define TI_200 (200)  /**< 遥测传输 [采样板交互] */
#define TI_201 (201)  /**< 状态传输 [采样板交互] */
#define TI_202 (202)  /**< 计量传输 */
#define TI_203 (203)  /**< 遥控交互 [采样板交互] */
#define TI_204 (204)  /**< SOE传输 [采样板交互] */
#define TI_205 (205)  /**< 故障事件传输 [采样板交互] */
#define TI_207 (207)  /**< 遥测扰动传输 [采样板交互] */
#define TI_208 (208)  /**< 按键操作传输 [采样板交互] */
#define TI_221 (221)  /**< 时间同步 [采样板交互] */
#define TI_222 (222)  /**< 日志信息传输 [采样板交互] */

/* =========================== 传输原因 (COT) =========================== */

#define COT_3   (3)
#define COT_5   (5)    /**< 请求 */
#define COT_6   (6)    /**< 激活 */
#define COT_7   (7)    /**< 正常确认 */
#define COT_8   (8)    /**< 终端响应 */
#define COT_20  (20)   /**< MD5不匹配 */

/* =========================== 信息体地址 =========================== */

#define TI_1_INFO_ADDR  (0)   /**< 独立编码参数 信息体地址 */
#define TI_5_INFO_ADDR  (0)   /**< 终端时间 信息体地址 */
#define TI_6_INFO_ADDR  (1)   /**< 终端状态读取 信息体地址 */
#define TI_9_INFO_ADDR  (0)   /**< 升级 信息体地址 */
#define TI_11_INFO_ADDR (0)   /**< 文件操作 信息体地址 */

/* =========================== 帧常量 =========================== */

#define ICP67_HEAD          (0x67)  /**< 帧头字符 */
#define ICP67_TAIL          (0x16)  /**< 帧尾字符 */
#define ICP67_HEAD_OVERHEAD  4       /**< head1(1)+len(2)+head2(1) */
#define ICP67_FRAME_OVERHEAD 6       /**< head_overhead(4)+crc(1)+tail(1) */
#define ICP67_UPGRADE_TYPE   1       /**< 升级类型 */
#define ICP67_NAME_MAX       256     /**< 文件名最大长度 */
#define ICP67_TM_STRUCT_LEN  7       /**< 时间结构体长度 */

/* TI_11 文件操作子命令 */
#define TI_11_SUB_CMD_DIR        (1)
#define TI_11_SUB_CMD_FILE_READ  (2)
#define TI_11_SUB_CMD_FILE_WRITE (3)
#define TI_11_SUB_CMD_FILE_DEL   (8)
#define TI_11_SUB_CMD_FILE_MOVE  (10)

/* TI_30 文件操作子命令 */
#define TI_30_CMD_1 (1)
#define TI_30_CMD_3 (3)

/* =========================== ASDU 帧结构 =========================== */

/* TI_1/TI_2: 独立编码参数 */
#pragma pack(1)
typedef struct
{
	uint8_t  md5[ICP67_MD5_LEN];  /**< MD5校验码 */
	uint16_t num;                 /**< 参数个数 */
	uint8_t  data[0];             /**< 参数数据 (柔性数组) */
}stru_ti_1_2;
#pragma pack()

/* TI_3: 自定义组合编码参数 — 分帧传输 */
#pragma pack(1)
typedef struct
{
	uint16_t total;     /**< 总参数个数 */
	uint16_t frame_no;  /**< 帧序号 (当前帧起始索引) */
	uint8_t  follow;    /**< 后续帧标志 0=最后一帧, 1=还有后续 */
	uint16_t num;       /**< 本帧参数个数 */
	uint8_t  data[0];   /**< 数据区 (柔性数组) */
}stru_ti_3_follow;
#pragma pack()

/* TI_3/TI_4: 自定义组合编码参数 — 通用 */
#pragma pack(1)
typedef struct
{
	uint16_t total;     /**< 总参数个数 */
	uint16_t frame_no;  /**< 帧序号 */
	uint8_t  follow;    /**< 后续帧标志 */
	uint8_t  data[0];   /**< 数据区 (柔性数组) */
}stru_ti_3_4;
#pragma pack()

/* TI_3/TI_4 数据段 */
#pragma pack(1)
typedef struct
{
	uint8_t num;        /**< 参数个数 */
	uint8_t data[0];    /**< 数据区 (柔性数组) */
}stru_ti_3_4_data;
#pragma pack()

/* TI_11 子命令帧 */
#pragma pack(1)
typedef struct
{
	uint8_t cmd;        /**< 子命令 */
	uint8_t data[0];    /**< 数据区 (柔性数组) */
}stru_ti_11_cmd;
#pragma pack()

/* =========================== 文件操作子命令 =========================== */

#define FILE_CMD_1  (1)   /**< 读目录 */
#define FILE_CMD_2  (2)   /**< 读目录响应 */
#define FILE_CMD_3  (3)   /**< 读文件激活 */
#define FILE_CMD_4  (4)   /**< 读文件激活响应 */
#define FILE_CMD_5  (5)   /**< 读文件内容 */
#define FILE_CMD_6  (6)   /**< 读文件内容响应 */
#define FILE_CMD_7  (7)   /**< 写文件激活 */
#define FILE_CMD_8  (8)   /**< 写文件激活响应 */
#define FILE_CMD_9  (9)   /**< 写文件内容 */
#define FILE_CMD_10 (10)  /**< 写文件内容响应 */
#define FILE_CMD_11 (11)  /**< 写文件校验成功 */

/* =========================== TI_11 文件操作 ASDU =========================== */

/* 读目录 */
#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint32_t id;
	uint8_t  len;
	uint8_t  data[0];
}stru_ti_11_1;
#pragma pack()

/* 读目录时间信息 */
#pragma pack(1)
typedef struct
{
	uint8_t flag;
	uint8_t start_tm[ICP67_TM_STRUCT_LEN];
	uint8_t end_tm[ICP67_TM_STRUCT_LEN];
	uint8_t data[0];
}stru_ti_11_1_info;
#pragma pack()

/* 读目录响应 */
#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint8_t  result;
	uint32_t id;
	uint8_t  follow;
	uint16_t num;
	uint8_t  data[0];
}stru_ti_11_2;
#pragma pack()

/* 读文件激活 */
#pragma pack(1)
typedef struct
{
	uint8_t cmd;
	uint8_t len;
	uint8_t data[0];
}stru_ti_11_3;
#pragma pack()

/* 读文件激活响应 */
#pragma pack(1)
typedef struct
{
	uint8_t cmd;
	uint8_t result;
	uint8_t len;
	uint8_t data[0];
}stru_ti_11_4;
#pragma pack()

/* 读文件内容 */
#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint32_t id;
	uint32_t offset;
	uint8_t  follow;
	uint16_t len;
	uint8_t  data[0];
}stru_ti_11_5;
#pragma pack()

/* 读文件内容响应 */
#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint32_t id;
	uint32_t offset;
	uint8_t  result;
	uint8_t  data[0];
}stru_ti_11_6;
#pragma pack()

/* 写文件激活 */
#pragma pack(1)
typedef struct
{
	uint8_t cmd;
	uint8_t len;
	uint8_t data[0];
}stru_ti_11_7;
#pragma pack()

/* 写文件激活响应 */
#pragma pack(1)
typedef struct
{
	uint8_t cmd;
	uint8_t result;
	uint8_t len;
	uint8_t data[0];
}stru_ti_11_8;
#pragma pack()

/* 写文件内容 */
#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint32_t id;
	uint32_t offset;
	uint8_t  follow;
	uint16_t len;
	uint8_t  data[0];
}stru_ti_11_9;
#pragma pack()

/* 写文件内容响应 */
#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint32_t id;
	uint32_t offset;
	uint8_t  result;
	uint8_t  md5[ICP67_MD5_LEN];
	uint8_t  data[0];
}stru_ti_11_10;
#pragma pack()

/* 写文件校验成功 */
#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint32_t id;
	uint8_t  result;
	uint8_t  md5[ICP67_MD5_LEN];
	uint8_t  data[0];
}stru_ti_11_11;
#pragma pack()

/* 文件ID、大小、校验信息 */
#pragma pack(1)
typedef struct
{
	uint32_t id;
	uint32_t size;
	uint16_t crc;
}stru_ti_11_file_info;
#pragma pack()

/* =========================== TI_30 录波文件压缩 ASDU =========================== */

/* 录波文件压缩控制命令 */
#define TI_30_CMD_1 (1)   /**< 录波文件压缩控制命令 */
#define TI_30_CMD_2 (2)   /**< 录波文件压缩控制命令响应 */
#define TI_30_CMD_3 (3)   /**< 压缩文件传输命令 */
#define TI_30_CMD_4 (4)   /**< 压缩文件传输命令响应 */

#pragma pack(1)
typedef struct
{
	uint8_t cmd;
	uint8_t zip_type;
	uint8_t len;
	uint8_t data[0];
}stru_ti_30_1;
#pragma pack()

#pragma pack(1)
typedef struct
{
	uint8_t cmd;
	uint8_t zip_type;
	uint8_t len;
	uint8_t data[0];
}stru_ti_30_2;
#pragma pack()

#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint8_t  file_no;
	uint32_t offset;
	uint16_t len;
	uint8_t  data[0];
}stru_ti_30_3;
#pragma pack()

#pragma pack(1)
typedef struct
{
	uint8_t  cmd;
	uint8_t  file_no;
	uint32_t offset;
	uint8_t  data[0];
}stru_ti_30_4;
#pragma pack()

/* =========================== 终端状态读取 ASDU =========================== */

#pragma pack(1)
typedef struct
{
	uint16_t st_num;
	uint8_t  st_data[0];
}stru_ti_6;
#pragma pack()

/* =========================== 遥测/遥信/计量传输 ASDU =========================== */

#pragma pack(1)
typedef struct
{
	uint16_t num;
	uint16_t addr;
	uint8_t  data[0];
}stru_ti_200_201_202;
#pragma pack()

/* =========================== 遥控交互 ASDU =========================== */

#pragma pack(1)
typedef struct
{
	uint16_t addr;
	uint8_t  cmd;
	uint8_t  status;
	uint8_t  data[0];
}stru_ti_203;
#pragma pack()

#define ICP67_TI_203_CMD_SELECT (1)  /**< 遥控选择 */
#define ICP67_TI_203_CMD_DIRECT (2)  /**< 遥控执行 */
#define ICP67_TI_203_CMD_CANCEL (3)  /**< 遥控取消 */

#define ICP67_TI_203_STATUS_ON  (1)  /**< 控合 */
#define ICP67_TI_203_STATUS_OFF (0)  /**< 控分 */

/* =========================== SOE/故障/扰动 ASDU =========================== */

#pragma pack(1)
typedef struct
{
	uint16_t num;
	uint8_t  data[0];
}stru_ti_204_205_207;
#pragma pack()

/* =========================== 内部交叉引用 =========================== */

/**
 * @brief 8-bit 累加校验和 (icp67_frame.c 实现, icp67_decode.c 引用)
 */
extern uint8_t crc_check_sum(uint8_t *p_data, uint16_t len);

/* =========================== 内部 API =========================== */

/**
 * @brief ICP67 帧搜索 — 扫描 0x67 帧头，验证长度/CRC/帧尾
 * @param p_data      输入数据缓冲区
 * @param len         输入数据长度
 * @param p_pos       输出: 帧在缓冲区中的起始位置
 * @param p_valid_len 输出: 有效帧长度
 * @return 0 找到有效帧, -1 未找到
 */
int icp67_search_frame(uint8_t *p_data, uint16_t len, uint16_t *p_pos, uint16_t *p_valid_len);

/**
 * @brief 环形缓冲区帧搜索 (零拷贝)
 * @param buf    环形缓冲区基址
 * @param size   缓冲区总大小
 * @param rptr   读指针 (当前有效数据的起始位置)
 * @param cnt    有效数据长度
 * @param p_pos  输出: 帧在环形缓冲中的偏移 (相对于 rptr)
 * @param p_valid_len 输出: 有效帧长度
 * @return 0 找到, -1 未找到
 *
 * @note 直接操作环形缓冲区指针, 无需调用方先 memcpy 全量数据
 */
int icp67_search_frame_in_ring(const uint8_t *buf, uint16_t size,
	uint16_t rptr, uint16_t cnt,
	uint16_t *p_pos, uint16_t *p_valid_len);

/**
 * @brief ICP67 帧解码分发 — 从帧头读取 TI，查表调用对应 decode 函数
 * @param p_icp67  协议实例
 * @param p_data   帧数据
 * @param len      帧长度
 * @return 0 解码成功, -1 解码失败
 */
int icp67_decode(stru_icp67 *p_icp67, uint8_t *p_data, uint16_t len);

/**
 * @brief ICP67 重传定时器处理 — 检查超时 + 触发重发
 * @param p_icp67  协议实例
 */
void icp67_timer_handler(stru_icp67 *p_icp67);

/**
 * @brief 构造 ICP67 帧头
 * @param dst       目标设备
 * @param ti        类型标识
 * @param cot       传输原因
 * @param info_addr 信息地址
 * @param p_tx      发送缓冲区 (输入输出)
 * @param tx_len    发送长度 (输入输出)
 */
void icp67_make_head(uint8_t dst, uint8_t ti, uint8_t cot, uint16_t info_addr, uint8_t *p_tx, uint16_t *tx_len);

/**
 * @brief 构造 ICP67 帧尾 (CRC + 0x16)
 * @param p_tx   发送缓冲区
 * @param tx_len 发送长度 (输入输出)
 */
void icp67_make_tail(uint8_t *p_tx, uint16_t *tx_len);

/**
 * @brief 打印 ICP67 帧 (调试用)
 * @param p_data 帧数据
 * @param len    帧长度
 */
void icp67_show_frame(uint8_t *p_data, uint16_t len);

/**
 * @brief 设置重传标志 (线程安全)
 * @param p_icp67     协议实例
 * @param flag        新标志值
 * @param resend_cnt  重发计数
 * @param tm_cnt      定时器计数
 */
void icp67_rtx_flag_set(stru_icp67 *p_icp67, uint8_t flag, uint8_t resend_cnt, uint32_t tm_cnt);

/**
 * @brief 获取重传标志 (线程安全)
 * @param p_icp67     协议实例
 * @param flag        输出: 当前标志
 * @param resend_cnt  输出: 重发计数
 * @param tm_cnt      输出: 定时器计数
 */
void icp67_rtx_flag_get(stru_icp67 *p_icp67, uint8_t *flag, uint8_t *resend_cnt, uint32_t *tm_cnt);

/**
 * @brief 重传计数递增 (线程安全)
 * @param p_icp67  协议实例
 */
void icp67_rtx_resend_inc(stru_icp67 *p_icp67);

/**
 * @brief 定时器计数递增 (线程安全)
 * @param p_icp67  协议实例
 */
void icp67_rtx_tm_inc(stru_icp67 *p_icp67);

#ifdef __cplusplus
}
#endif

#endif /* _ICP67_H_ */
