/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : bsp_module.h
  * @brief          : Board support package module management header file
  ******************************************************************************
  */
/* USER CODE END Header */

#ifndef BSP_MODULE_H
#define BSP_MODULE_H

#include "hal.h"

/**
 * @brief BSP module type definitions
 */
typedef enum {
    BSP_MODULE_TYPE_LED = 0,
    BSP_MODULE_TYPE_BUTTON,
    BSP_MODULE_TYPE_UART,
    BSP_MODULE_TYPE_SPI,
    BSP_MODULE_TYPE_I2C,
    BSP_MODULE_TYPE_CAN,
    BSP_MODULE_TYPE_ADC,
    BSP_MODULE_TYPE_DAC,
    BSP_MODULE_TYPE_TIMER,
    BSP_MODULE_TYPE_RTC,
    BSP_MODULE_TYPE_W25QXX,
    BSP_MODULE_TYPE_MAX
} bsp_module_type_t;

/**
 * @brief BSP module state definitions
 */
typedef enum {
    BSP_MODULE_STATE_UNINIT = 0,
    BSP_MODULE_STATE_INIT,
    BSP_MODULE_STATE_CONFIGURED,
    BSP_MODULE_STATE_RUNNING,
    BSP_MODULE_STATE_ERROR
} bsp_module_state_t;

/**
 * @brief BSP module priority definitions
 */
typedef enum {
    BSP_MODULE_PRIORITY_HIGHEST = 0,
    BSP_MODULE_PRIORITY_HIGH,
    BSP_MODULE_PRIORITY_MEDIUM,
    BSP_MODULE_PRIORITY_LOW,
    BSP_MODULE_PRIORITY_LOWEST
} bsp_module_priority_t;

/**
 * @brief BSP module configuration structure
 */
typedef struct bsp_module_config {
    bsp_module_type_t type;          /*!< Module type */
    const char* name;               /*!< Module name */
    bsp_module_priority_t priority;  /*!< Module priority */
    uint32_t version;               /*!< Module version */
    uint8_t instance;               /*!< Module instance */
    uint8_t enable;                 /*!< Module enable flag */
    void* config_data;              /*!< Module configuration data */
    size_t config_size;             /*!< Module configuration size */
    uint32_t dependencies;          /*!< Module dependencies bitmask */
} bsp_module_config_t;

/**
 * @brief BSP module operations structure
 */
typedef struct {
    hal_ret_t (*init)(void* config);          /*!< Module initialization function */
    hal_ret_t (*deinit)(void);               /*!< Module deinitialization function */
    hal_ret_t (*configure)(void* config);     /*!< Module configuration function */
    hal_ret_t (*start)(void);                 /*!< Module start function */
    hal_ret_t (*stop)(void);                  /*!< Module stop function */
    hal_ret_t (*reset)(void);                 /*!< Module reset function */
    bsp_module_state_t (*get_state)(void);       /*!< Module get state function */
    hal_ret_t (*control)(uint32_t cmd, void* param); /*!< Module control function */
} bsp_module_ops_t;

/**
 * @brief BSP module version structure
 */
typedef struct {
    uint8_t major;
    uint8_t minor;
    uint8_t patch;
} bsp_module_version_t;

/**
 * @brief Forward declaration of bsp_module_t
 */
typedef struct bsp_module bsp_module_t;

/**
 * @brief BSP module event callback type
 */
typedef hal_ret_t (*bsp_module_event_callback_t)(const bsp_module_t* sender, uint32_t event, void* data);

/**
 * @brief BSP module structure
 */
typedef struct bsp_module {
    bsp_module_config_t config;      /*!< Module configuration */
    bsp_module_ops_t ops;            /*!< Module operations */
    bsp_module_state_t state;        /*!< Module state */
    bsp_module_version_t version;    /*!< Module version */
    struct bsp_module* next;         /*!< Pointer to next module in the list */
    struct bsp_module* prev;         /*!< Pointer to previous module in the list */
    void* private_data;              /*!< Module private data */
    bsp_module_event_callback_t event_callback; /*!< Event callback */
} bsp_module_t;

/**
 * @brief BSP module event definitions
 */
#define BSP_MODULE_EVENT_INIT      (1 << 0)  /*!< Module initialized */
#define BSP_MODULE_EVENT_DEINIT    (1 << 1)  /*!< Module deinitialized */
#define BSP_MODULE_EVENT_START     (1 << 2)  /*!< Module started */
#define BSP_MODULE_EVENT_STOP      (1 << 3)  /*!< Module stopped */
#define BSP_MODULE_EVENT_ERROR     (1 << 4)  /*!< Module error */
#define BSP_MODULE_EVENT_CONFIG    (1 << 5)  /*!< Module configured */
#define BSP_MODULE_EVENT_CUSTOM    (1 << 8)  /*!< Custom module event base */

/**
 * @brief BSP module auto-registration macros
 */
#define BSP_MODULE_REGISTER(module) \
    static const bsp_module_config_t __bsp_module_##module##_config = { \
        .type = BSP_MODULE_TYPE_##module, \
        .name = #module, \
        .priority = BSP_MODULE_PRIORITY_MEDIUM, \
        .version = 1, \
        .instance = 0, \
        .enable = 1, \
        .config_data = NULL, \
        .config_size = 0, \
        .dependencies = 0 \
    }; \
    static bsp_module_t __bsp_module_##module = { \
        .config = __bsp_module_##module##_config, \
        .state = BSP_MODULE_STATE_UNINIT, \
        .version = {1, 0, 0}, \
        .event_callback = NULL \
    };

#define BSP_MODULE_REGISTER_FULL(module, type, priority, instance, deps) \
    static const bsp_module_config_t __bsp_module_##module##_config = { \
        .type = (type), \
        .name = #module, \
        .priority = (priority), \
        .version = 1, \
        .instance = (instance), \
        .enable = 1, \
        .config_data = NULL, \
        .config_size = 0, \
        .dependencies = (deps) \
    }; \
    static bsp_module_t __bsp_module_##module = { \
        .config = __bsp_module_##module##_config, \
        .state = BSP_MODULE_STATE_UNINIT, \
        .version = {1, 0, 0}, \
        .event_callback = NULL \
    };

#define BSP_MODULE_REGISTER_AT_STARTUP(module) \
    BSP_MODULE_REGISTER(module) \
    __attribute__((constructor)) static void __bsp_register_##module##_at_startup(void) { \
        bsp_module_register(&__bsp_module_##module); \
    }

/**
 * @brief BSP module manager structure
 */
typedef struct {
    bsp_module_t* modules[BSP_MODULE_TYPE_MAX]; /*!< Modules by type */
    bsp_module_t* module_list;       /*!< Linked list of all modules */
    uint32_t module_count;           /*!< Total number of modules */
} bsp_module_manager_t;

/**
 * @brief Initialize BSP module manager
 * @retval HAL status code
 */
hal_ret_t bsp_module_manager_init(void);

/**
 * @brief Register a BSP module
 * @param module: Pointer to module structure
 * @retval HAL status code
 */
hal_ret_t bsp_module_register(bsp_module_t* module);

/**
 * @brief Unregister a BSP module
 * @param module: Pointer to module structure
 * @retval HAL status code
 */
hal_ret_t bsp_module_unregister(bsp_module_t* module);

/**
 * @brief Initialize all registered BSP modules
 * @retval HAL status code
 */
hal_ret_t bsp_module_init_all(void);

/**
 * @brief Deinitialize all registered BSP modules
 * @retval HAL status code
 */
hal_ret_t bsp_module_deinit_all(void);

/**
 * @brief Start all registered BSP modules
 * @retval HAL status code
 */
hal_ret_t bsp_module_start_all(void);

/**
 * @brief Stop all registered BSP modules
 * @retval HAL status code
 */
hal_ret_t bsp_module_stop_all(void);

/**
 * @brief Initialize a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @retval HAL status code
 */
hal_ret_t bsp_module_init(bsp_module_type_t type, uint8_t instance);

/**
 * @brief Deinitialize a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @retval HAL status code
 */
hal_ret_t bsp_module_deinit(bsp_module_type_t type, uint8_t instance);

/**
 * @brief Configure a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @param config: Module configuration data
 * @param size: Module configuration size
 * @retval HAL status code
 */
hal_ret_t bsp_module_configure(bsp_module_type_t type, uint8_t instance, void* config, size_t size);

/**
 * @brief Start a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @retval HAL status code
 */
hal_ret_t bsp_module_start(bsp_module_type_t type, uint8_t instance);

/**
 * @brief Stop a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @retval HAL status code
 */
hal_ret_t bsp_module_stop(bsp_module_type_t type, uint8_t instance);

/**
 * @brief Reset a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @retval HAL status code
 */
hal_ret_t bsp_module_reset(bsp_module_type_t type, uint8_t instance);

/**
 * @brief Get state of a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @param state: Pointer to store module state
 * @retval HAL status code
 */
hal_ret_t bsp_module_get_state(bsp_module_type_t type, uint8_t instance, bsp_module_state_t* state);

/**
 * @brief Control a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @param cmd: Control command
 * @param param: Control parameter
 * @retval HAL status code
 */
hal_ret_t bsp_module_control(bsp_module_type_t type, uint8_t instance, uint32_t cmd, void* param);

/**
 * @brief Get a specific BSP module
 * @param type: Module type
 * @param instance: Module instance
 * @retval Pointer to module structure, or NULL if not found
 */
bsp_module_t* bsp_module_get(bsp_module_type_t type, uint8_t instance);

/**
 * @brief Get all modules of a specific type
 * @param type: Module type
 * @retval Pointer to module list, or NULL if no modules found
 */
bsp_module_t* bsp_module_get_by_type(bsp_module_type_t type);

/**
 * @brief Get module by name
 * @param name: Module name
 * @retval Pointer to module structure, or NULL if not found
 */
bsp_module_t* bsp_module_get_by_name(const char* name);

/**
 * @brief Get total number of registered modules
 * @retval Number of registered modules
 */
uint32_t bsp_module_get_count(void);

/**
 * @brief Check if all dependencies of a module are satisfied
 * @param module: Pointer to module structure
 * @retval HAL status code
 */
hal_ret_t bsp_module_check_dependencies(const bsp_module_t* module);

/**
 * @brief Get module manager instance
 * @retval Pointer to module manager structure
 */
bsp_module_manager_t* bsp_module_get_manager(void);

/**
 * @brief Register a module event callback
 * @param type: Module type
 * @param instance: Module instance
 * @param callback: Event callback function
 * @retval HAL status code
 */
hal_ret_t bsp_module_register_event_callback(bsp_module_type_t type, uint8_t instance, bsp_module_event_callback_t callback);

/**
 * @brief Trigger a module event
 * @param module: Pointer to module structure
 * @param event: Event to trigger
 * @param data: Event data
 * @retval HAL status code
 */
hal_ret_t bsp_module_trigger_event(const bsp_module_t* module, uint32_t event, void* data);

/**
 * @brief Find modules by priority range
 * @param min_priority: Minimum priority
 * @param max_priority: Maximum priority
 * @param count: Pointer to store number of modules found
 * @retval Pointer to array of module pointers, or NULL if no modules found
 */
bsp_module_t** bsp_module_find_by_priority_range(bsp_module_priority_t min_priority, bsp_module_priority_t max_priority, uint32_t* count);

/**
 * @brief Set module enable/disable state
 * @param type: Module type
 * @param instance: Module instance
 * @param enable: Enable flag
 * @retval HAL status code
 */
hal_ret_t bsp_module_set_enable(bsp_module_type_t type, uint8_t instance, uint8_t enable);

/**
 * @brief Check if module is enabled
 * @param type: Module type
 * @param instance: Module instance
 * @param enable: Pointer to store enable state
 * @retval HAL status code
 */
hal_ret_t bsp_module_is_enabled(bsp_module_type_t type, uint8_t instance, uint8_t* enable);

/**
 * @brief Set module priority
 * @param type: Module type
 * @param instance: Module instance
 * @param priority: New priority
 * @retval HAL status code
 */
hal_ret_t bsp_module_set_priority(bsp_module_type_t type, uint8_t instance, bsp_module_priority_t priority);

/**
 * @brief Get module priority
 * @param type: Module type
 * @param instance: Module instance
 * @param priority: Pointer to store priority
 * @retval HAL return code
 */
hal_ret_t bsp_module_get_priority(bsp_module_type_t type, uint8_t instance, bsp_module_priority_t* priority);

#endif /* BSP_MODULE_H */