#pragma once 

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "resend_crc.h"
#include "os/os.h"
#include "os/os_common.h"
#include "console.h"
#include "shell/sh_vset.h"
//  帧数据量
#define RESEND_HEADER_SIZE 2
#define RESEND_CMD_SIZE 1
#define RESEND_SEQ_SIZE 1
#define RESEND_RETRY_CNT_SIZE 1
#define RESEND_LEN_SIZE 2
#define RESEND_DATA_SIZE 1024
#define RESEND_CRC_SIZE 2
#define RESEND_MAX_PAYLOAD (RESEND_HEADER_SIZE + RESEND_CMD_SIZE + RESEND_SEQ_SIZE + RESEND_RETRY_CNT_SIZE + RESEND_LEN_SIZE + RESEND_CRC_SIZE)
#define RESEND_FRAME_SIZE RESEND_HEADER_SIZE + RESEND_CMD_SIZE + RESEND_SEQ_SIZE + RESEND_RETRY_CNT_SIZE + RESEND_LEN_SIZE + RESEND_DATA_SIZE + RESEND_CRC_SIZE
//  帧头
#define RESEND_HEADER_0 0xFD
#define RESEND_HEADER_1 0xFE

#define RESEND_MAX_RETRY_CNT 0
//  命令类型
typedef enum
{
    RESEND_CMD_DATA = 0x01,
    RESEND_CMD_ACK = 0x02,
    RESEND_CMD_PARAM = 0x03,
    RESEND_CMD_GET_PARAM = 0x04,
    RESEND_CMD_SET_PARAM = 0x05,

    RESEND_CMD_DATA_ACK = 0x06,

    RESEND_CMD_ERROR_CODE = 0x07,

    RESEND_CMD_OTA_GET_PARAM = 0x010,
    RESEND_CMD_OTA_START = 0x011,
    RESEND_CMD_OTA_DATA = 0x012,
    RESEND_CMD_OTA_END = 0x013,

    RESEND_CMD_FC_ISP_GET_PARAM = 0x020,
    RESEND_CMD_FC_ISP_START = 0x021,
    RESEND_CMD_FC_ISP_DATA = 0x022,
    RESEND_CMD_FC_ISP_END = 0x023
}resend_cmd_type_e;
//  帧解析状态
typedef enum
{
    RESEND_IDLE = 0,
    RESEND_HDR,
    RESEND_SEQ,
    RESEND_CMD,
    RESEND_RETRY_CNT,
    RESEND_LEN_1,
    RESEND_LEN_2,
    RESEND_DATA,
    RESEND_CRC_1,
    RESEND_CRC_2
}resend_c_state_e;
//  帧状态
typedef struct
{
    resend_c_state_e c_state;        //目前解析数据状态
    uint8_t resend_flag;            //该数据是否是重发数据
    uint8_t ack_flag;               //应答信号标志位
    uint16_t data_offset;           //数据偏移
}resend_status_t;
//  帧
typedef struct 
{
    uint8_t header_0;                         // 帧头
    uint8_t header_1;                         // 帧头
    uint8_t seq;                            // 帧序号
    uint8_t cmd;                            // 命令
    uint8_t retry_cnt;                      // 重发次数
    uint16_t len;                           // 帧长度
    uint8_t payload[RESEND_DATA_SIZE];      // 帧数据
    uint16_t crc;                           // 帧CRC
}resend_frame_t;
// 帧驱动
typedef struct
{
    resend_frame_t rx_frame;                // 接收帧
    resend_frame_t tx_frame;                // 发送帧
    resend_status_t status;                 // 帧状态

    uint8_t handle_flag;                    // 接收请求帧处理标志

    int (*send)(void* data, uint16_t len, int timeout);  // 发送数据
    int (*recv)(void* data, uint16_t len, int timeout);  // 接收数据
    int (*get_length )(void);                               // 获取数据长度
    void (*resend_user_parse)(void *resend_device);
}resend_device_t;

/**
 * @brief 协议初始化
 */
void resend_init(resend_device_t *resend_device, int (*send)(void* data, uint16_t len, int timeout), int (*recv)(void* data, uint16_t len, int timeout), int (*get_length )(void), void (*resend_user_parse)(void *resend_device));

/**
 * @brief 设置参数
 */
void resend_set(resend_device_t *resend_device);
/**
 * @brief 封包
 */
int resend_encode(resend_device_t *resend_device, void *out, uint8_t cmd, void* data, uint16_t len);
/**
 * @brief 解包
 */
int resend_decode(resend_device_t *resend_device, uint8_t c);

/**
 * @brief 发送无数据命令
 */
int resend_send_cmd(resend_device_t *resend_device, uint8_t cmd, int timeout);

/**
 * @brief 数据发送
 */
int resend_send_data(resend_device_t *resend_device, uint8_t cmd, void* data, uint16_t len, int timeout);

/**
 * @brief 数据接收
 */
int resend_recv_data(resend_device_t *resend_device, int timeout);

/**
 * @brief 数据解析
 */
int resend_parse_data(resend_device_t *resend_device);


/* 接口函数 */
int resend_send(void* data, uint16_t len, int timeout);
int resend_recv(void* data, uint16_t len, int timeout);
int resend_get_length(void);
void resend_user_parse(void *resend_device);