#pragma once

#include <stdint.h>
#include "board_config.h"

#define MAX_PUBLIC_KEYS 5
#define PUBLIC_KEY_LEN 32
#define PARAM_NAME_MAX_LEN 16 // 参数名最长

#define PARAM_FLAG_NONE 0 
#define PARAM_FLAG_PASSWORD (1U<<0)
#define PARAM_FLAG_HIDDEN (1U<<1)

class Parameters {
public:
#if defined(PIN_CAN_TERM)
    uint8_t can_term = !CAN_TERM_EN; // 是否用CAN终端电阻
#endif
    int8_t lock_level;  // 固件锁等级（-1=无锁，0-2=不同安全级别）
    uint8_t can_node; // CAN总线节点ID
    uint8_t bcast_powerup;  // 上电即广播（1=是，0=等待有效位置）
    uint32_t baudrate = 57600; // 串口波特率
    uint8_t ua_type;  // 无人机类型
    uint8_t id_type; // ID类型
    char uas_id[21] = "ABCD123456789";// 无人机ID（20字符）
    // 第二个ID（可选，用于多架次）
    uint8_t ua_type_2; 
    uint8_t id_type_2;
    char uas_id_2[21] = "ABCD123456789";
    float wifi_nan_rate; // WiFi NAN广播频率(Hz)
    float wifi_beacon_rate;  // WiFi Beacon广播频率(Hz)
    float wifi_power; // WiFi发射功率(dBm)
    float bt4_rate; // 经典蓝牙广播频率
    float bt4_power;  // 经典蓝牙功率
    float bt5_rate;  // BLE长距离广播频率
    float bt5_power;   // BLE长距离功率
    uint8_t done_init;  // 首次初始化完成标志
    uint8_t protocol; // 协议选择：0=国际，1=国标
    uint8_t webserver_enable;  // 启用Web服务器
    uint8_t mavlink_sysid; // mavlink系统id默认值通常是 0 或 245
    char wifi_ssid[21] = ""; // WiFi名称
    char wifi_password[21] = "ArduRemoteID"; // WiFi密码
    uint8_t wifi_channel = 6;// WiFi信道
    uint8_t to_factory_defaults = 0; // 恢复出厂设置
    uint8_t options; // 功能选项（位掩码）
    struct {
        char b64_key[64];  // Base64编码的公钥
    } public_keys[MAX_PUBLIC_KEYS]; // 最多5个公钥
    // 参数类型枚举
    enum class ParamType {
        NONE=0,     // 无
        UINT8=1,    // 8位无符号整数
        UINT32=2,   // 32位无符号整数
        FLOAT=3,    // 浮点数
        CHAR20=4,   // 20字符字符串
        CHAR64=5,   // 64字符字符串
        INT8=6,     // 8位有符号整数
    };
    // 参数描述结构体
    struct Param {
        char name[PARAM_NAME_MAX_LEN+1];// 参数名（如"WIFI_SSID"）
        ParamType ptype; // 参数类型
        const void *ptr;  // 指向实际变量的指针
        float default_value;  // 默认值
        float min_value;  // 最小值
        float max_value;   // 最大值
        uint16_t flags;   // 标志位（密码、隐藏等）
        uint8_t min_len; // 最小长度（字符串用）
        // 操作方法
        // 设置值
        void set_float(float v) const; 
        void set_uint8(uint8_t v) const;
        void set_int8(int8_t v) const;
        void set_uint32(uint32_t v) const;
        void set_char20(const char *v) const;
        void set_char64(const char *v) const;
        // 获取值
        uint8_t get_uint8() const;
        int8_t get_int8() const;
        uint32_t get_uint32() const;
        float get_float() const;
        const char *get_char20() const;
        const char *get_char64() const;
        bool get_as_float(float &v) const;
        void set_as_float(float v) const;
    };
    static const struct Param params[]; // 只是声明，不分配内存
    // 参数查找
    static const Param *find(const char *name); // 按名字找
    static const Param *find_by_index(uint16_t idx);  // 按索引找
    static const Param *find_by_index_float(uint16_t idx);  // 找可转浮点的参数

    void init(void); // 初始化

    bool have_basic_id_info(void) const; // 检查是否有id信息
    bool have_basic_id_2_info(void) const; // 检查是否有第2个id信息

    bool set_by_name_uint8(const char *name, uint8_t v); // 设置UINT8
    bool set_by_name_int8(const char *name, int8_t v); // 设置INT8
    bool set_by_name_char64(const char *name, const char *s);// 设置字符串
    bool set_by_name_string(const char *name, const char *s); // 通用字符串设置

    /*
      return a public key
    */
    bool get_public_key(uint8_t i, uint8_t key[32]) const; // 获取公钥
    bool set_public_key(uint8_t i, const uint8_t key[32]);// 设置公钥
    bool remove_public_key(uint8_t i); // 删除公钥
    bool no_public_keys(void) const; // 检查是否有公钥

    static uint16_t param_count_float(void); // 统计可浮点化的参数数量 排除字符串等非数值类型
    static int16_t param_index_float(const Param *p); // 获取参数的浮点索引 返回它在浮点参数列表中的索引位置（不是原始参数表的索引）

private:
    void load_defaults(void); // 加载默认参数
};

// bits for OPTIONS parameter
#define OPTIONS_FORCE_ARM_OK (1U<<0)
#define OPTIONS_DONT_SAVE_BASIC_ID_TO_PARAMETERS (1U<<1)
#define OPTIONS_PRINT_RID_MAVLINK (1U<<2)
// protocol
#define PROTOCOL_EU 0
#define PROTOCOL_CN2023 1
#define PROTOCOL_GB2025 2
extern Parameters g;
