#ifndef __BT_MGR_H__
#define __BT_MGR_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "rtthread.h"
#include "bts2_app_inc.h"
#include <stdbool.h>
#include <stdint.h>

#include "rtdef.h"

/**
 * @brief 蓝牙管理器事件枚举    
 */
typedef enum {
    BT_MGR_EVENT_STACK_READY = 0,           /**< 蓝牙栈就绪事件 */
    BT_MGR_EVENT_CONNECTED,                 /**< 蓝牙连接事件 */
    BT_MGR_EVENT_DISCONNECTED,       /**< 蓝牙正常断开事件 */
    BT_MGR_EVENT_ABNORMAL_DISCONNECTED,     /**< 蓝牙异常断开事件 */

    BT_MGR_EVENT_RECONNECTED_START,         /**< 蓝牙重连开始事件 */
    BT_MGR_EVENT_RECONNECTED_HANDLE,        /**< 蓝牙重连处理事件 */
    BT_MGR_EVENT_RECONNECTED_STOP,          /**< 蓝牙重连停止事件 */
    

    BT_MGR_EVENT_PAN_RECONNECTED_START,             /**< 蓝牙PAN连接事件 */
    BT_MGR_EVENT_PAN_RECONNECTED_HANDLE,           /**< 蓝牙PAN重连事件 */     
    BT_MGR_EVENT_PAN_RECONNECTED_STOP,          /**< 蓝牙PAN断开事件 */

    BT_MGR_EVENT_DHCP_RECONNECTED_START,             /**< 蓝牙DHCP连接事件 */
    BT_MGR_EVENT_DHCP_RECONNECTED_HANDLE,           /**< 蓝牙DHCP重连事件 */     
    BT_MGR_EVENT_DHCP_RECONNECTED_STOP,          /**< 蓝牙DHCP断开事件 */
    BT_MGR_EVENT_DHCP_RECONNECT_SUCCESS,              /**< 蓝牙DHCP成功事件 */

} bt_mgr_event_e;



/**
 * @brief 重连参数结构体
 * @details 该结构体包含重连状态、尝试次数、时间间隔和定时器等。    
*/
struct reconnect_params_t {
    bool is_reconnecting;               /**< 是否正在重连 */
    uint32_t current_attempts;          /**< 重连尝试次数 */
    uint32_t max_attempts;              /**< 重连最大尝试次数 */
    uint32_t interval_ms;               /**< 重连时间间隔 */
    const char *timer_name;             /**< 重连定时器名称 */
    rt_timer_t timer;                   /**< 重连定时器 */
};

/**
 * @brief 蓝牙重连参数结构体
 * @details 该结构体包含蓝牙连接状态与重连参数，
 *          如是否已连接、是否正在重连、重连尝试次数、时间间隔等。
*/  
struct bt_reconnect_params_t {
    bool is_connected;                  /**< 是否已连接 */
    struct reconnect_params_t reconnect;/**< 蓝牙重连参数 */
};

/**
 * @brief 蓝牙PAN重连参数结构体
 * @details 该结构体包含蓝牙PAN连接状态与重连参数，
 *          如是否已连接、是否正在重连、重连尝试次数、时间间隔等。
*/      
struct pan_reconnect_params_t {
    bool is_connected;                  /**< 是否已连接 */
    struct reconnect_params_t reconnect;/**< 蓝牙PAN重连参数 */
};

/**
 * @brief 蓝牙DHCP重连参数结构体
 * @details 该结构体包含蓝牙DHCP获取地址的相关参数，
 *          如是否正在重连、重连尝试次数、时间间隔等。
*/      
struct dhcp_reconnect_params_t {
    struct reconnect_params_t reconnect;/**< 蓝牙DHCP重连参数 */
};

/**
 * @brief A2DP参数结构体
 * @details 该结构体包含A2DP播放状态控制参数，
 *          如是否支持播放状态控制等。
*/
struct a2dp_params_t{
    bool play_state;                    /**< 是否支持播放状态控制 */
};

/**
 * @brief AVRCP参数结构体
 * @details 该结构体包含AVRCP绝对音量控制参数，
 *          如是否支持绝对音量控制等。
*/
struct avrcp_params_t{
    bool abs_volume_enable;             /**< 是否支持绝对音量控制 */
};

/**
 * @brief 蓝牙管理器结构体
 * @details 该结构体包含蓝牙连接状态、重连参数、邮箱和线程等。
*/  
struct bt_mgr_t{
    bool is_initlized;                  /**< 是否已初始化 */

    struct bt_reconnect_params_t bt;    /**< 蓝牙重连参数 */
    struct pan_reconnect_params_t pan;  /**< 蓝牙PAN重连参数 */
    struct dhcp_reconnect_params_t dhcp;/**< 蓝牙DHCP重连参数 */
    struct a2dp_params_t a2dp;          /**< A2DP参数 */
    struct avrcp_params_t avrcp;        /**< AVRCP参数 */

    bt_notify_device_mac_t mac_addr;    /**< 蓝牙设备地址 */
    rt_mailbox_t mbox;                  /**< 邮箱 */
    struct rt_thread thread;            /**< 线程 */
};

/*
 * @brief 初始化蓝牙管理器
 * @return 初始化结果
*/
rt_err_t bt_mgr_init(void);

/**
 * @brief 蓝牙管理器线程入口函数
 * @param parameter 线程参数
*/
static void bt_mgr_thread_entry_handle(void *parameter);

/**
 * @brief 蓝牙管理器通知事件处理函数
 * @param type 通知事件类型
 * @param event_id 通知事件ID
 * @param data 通知事件数据
 * @param data_len 通知事件数据长度
 * @return 处理结果 0: 成功 -1: 失败
*/
static int bt_mgr_notify_event_handle(uint16_t type, uint16_t event_id, uint8_t *data, uint16_t data_len);





/**
 * @brief 启动重连定时器
 * @details 检查重连定时器是否为空, 如果为空, 则初始化重连定时器, 并启动重连定时器
 * @param reconnect 重连参数结构体指针
 * @param timeout_handler 超时处理函数指针
 * @param parameter 超时处理函数参数指针
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败   
*/
static rt_err_t bt_mgr_reconnect_timer_start(struct reconnect_params_t *reconnect,
                                            void (*timeout_handler)(void *parameter),
                                            void *parameter);

                                            /**
 * @brief 停止重连定时器
 * @details 检查重连定时器是否为空, 如果不为空, 则停止重连定时器, 并将重连定时器指针设为NULL
 * @param reconnect 重连参数结构体指针
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败   
*/  
static rt_err_t bt_mgr_reconnect_timer_stop(struct reconnect_params_t *reconnect);

/**
 * @brief 启动蓝牙重连定时器
 * @details 检查重连定时器是否为空, 如果为空, 则初始化重连定时器, 并启动重连定时器  
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败   
*/
static rt_err_t bt_mgr_bt_timer_start(void);

/**
 * @brief 停止蓝牙重连定时器
 * @details 检查重连定时器是否为空, 如果不为空, 则停止重连定时器, 并将重连定时器指针设为NULL
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败   
*/
static rt_err_t bt_mgr_bt_timer_stop(void);

/**
 * @brief 蓝牙断线重连超时处理函数
 * @details 检查重连次数是否超过最大值, 如果没有超过, 则尝试连接A2DP协议, 如果超过, 则发送蓝牙重连失败事件
 * @param parameter 定时器参数  
*/
static void bt_mgr_bt_timeout_handle(void *parameter);

/**
 * @brief 蓝牙断线重连处理函数
 * @details 检查重连次数是否超过最大值, 如果没有超过, 则尝试连接A2DP协议, 如果超过, 则发送蓝牙重连失败事件
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败   
*/
static rt_err_t bt_mgr_bt_reconnect_handle(void);

/**
 * @brief PAN重连定时器开始
 * @details 检查重连定时器是否为空, 如果为空, 则初始化重连定时器, 并启动重连定时器  
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败  
*/
static rt_err_t bt_mgr_pan_timer_start(void);

/**
 * @brief PAN重连定时器停止
 * @details 检查重连定时器是否为空, 如果不为空, 则停止重连定时器, 并将重连定时器指针设为NULL
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败       
*/
static rt_err_t bt_mgr_pan_timer_stop(void);

/**
 * @brief PAN断线重连超时处理函数
 * @details 检查重连次数是否超过最大值, 如果没有超过, 则尝试连接HID协议, 如果超过, 则发送蓝牙重连失败事件
 * @param parameter 定时器参数  
*/  
static void bt_mgr_pan_timeout_handle(void *parameter);

/**
 * @brief PAN断线重连处理函数
 * @details 检查重连次数是否超过最大值, 如果没有超过, 则尝试连接HID协议, 如果超过, 则发送蓝牙重连失败事件
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败       
*/
static rt_err_t bt_mgr_pan_reconnect_handle(void);

/**
 * @brief DHCP定时器启动函数
 * @details 检查DHCP定时器是否为空, 如果为空, 则初始化DHCP定时器, 并启动DHCP定时器  
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败   
*/
static rt_err_t bt_mgr_dhcp_timer_start(void);

/**
 * @brief DHCP定时器停止函数
 * @details 检查DHCP定时器是否为空, 如果不为空, 则停止DHCP定时器, 并将DHCP定时器指针设为NULL    
*/  
static rt_err_t bt_mgr_dhcp_timer_stop(void);

/**
 * @brief DHCP定时器超时处理函数
 * @details 检查DHCP定时器是否为空, 如果不为空, 则停止DHCP定时器, 并发送DHCP获取IP事件  
 * @param parameter 定时器参数
*/
static void bt_mgr_dhcp_timeout_handle(void *parameter);

/**
 * @brief DHCP重连处理函数
 * @details 增加DHCP获取地址尝试次数, 并尝试连接PAN协议, 如果成功, 则发送成功事件, 否则发送失败事件
 * @return rt_err_t 错误码, RT_EOK表示成功, -RT_ERROR表示失败   
*/ 
static rt_err_t bt_mgr_dhcp_reconnect_handle(void);


/**
 * @brief 检查蓝牙网络是否已获取有效 IP
 * @details 检查默认网络接口是否存在, 如果不存在, 则直接返回失败, 否则调用 lwIP 内部函数, 判断 DHCP 是否已拿到地址
 * @return true  已获取到有效地址, 网络可用
 *         false 仍在获取中或获取失败
*/
static bool bt_mgr_dhcp_get_ip(void);



/**
 * @brief 设置蓝牙本地名称
 * @details 当 BT_NAME_MAC_ENABLE 定义时，将蓝牙本地名称设置为 name-XX:XX:XX:XX:XX:XX，
 *          其中 XX:XX:XX:XX:XX:XX 为蓝牙设备的 MAC 地址
 * @param name 蓝牙本地名称
 * @return rt_err_t 错误码，RT_EOK 表示成功，其他值表示失败
 */     
rt_err_t bt_mgr_set_local_name(const char *name);

#ifdef __cplusplus
}
#endif

#endif  /* __BT_MGR_H__ */


