/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : bsp_module.c
  * @brief          : 板级支持包模块管理源文件
  ******************************************************************************
  */
/* USER CODE END Header */

#include "bsp_module.h"
#include <string.h>

/**
 * @brief 模块管理器实例
 */
static bsp_module_manager_t bsp_module_manager;

/**
 * @brief 初始化 BSP 模块管理器
 * @retval HAL 状态码
 */
hal_ret_t bsp_module_manager_init(void) {
    /* Clear module manager */
    memset(&bsp_module_manager, 0, sizeof(bsp_module_manager));
    
    /* Initialize module arrays */
    for (uint8_t i = 0; i < BSP_MODULE_TYPE_MAX; i++) {
        bsp_module_manager.modules[i] = NULL;
    }
    
    bsp_module_manager.module_list = NULL;
    bsp_module_manager.module_count = 0;
    
    return HAL_RET_OK;
}

/**
 * @brief 注册一个 BSP 模块
 * @param module: 指向模块结构体的指针
 * @retval HAL 状态码
 */
hal_ret_t bsp_module_register(bsp_module_t* module) {
    if (module == NULL) {
        return HAL_RET_INVALID_PARAM;
    }
    
    if (module->config.type >= BSP_MODULE_TYPE_MAX) {
        return HAL_INVALID_PARAM;
    }
    
    /* Check if module already exists */
    if (bsp_module_get(module->config.type, module->config.instance) != NULL) {
        return HAL_RESOURCE_LOCKED;
    }
    
    /* Initialize module state */
    module->state = BSP_MODULE_STATE_UNINIT;
    module->next = NULL;
    module->prev = NULL;
    
    /* Add module to the linked list */
    if (bsp_module_manager.module_list == NULL) {
        bsp_module_manager.module_list = module;
    } else {
        /* Insert module at the end of the list */
        bsp_module_t* current = bsp_module_manager.module_list;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = module;
        module->prev = current;
    }
    
    /* Add module to the type-specific list */
    if (bsp_module_manager.modules[module->config.type] == NULL) {
        bsp_module_manager.modules[module->config.type] = module;
    } else {
        /* Insert module at the end of the type-specific list */
        bsp_module_t* current = bsp_module_manager.modules[module->config.type];
        while (current->next != NULL && current->config.type == module->config.type) {
            current = current->next;
        }
        if (current->config.type == module->config.type) {
            current->next = module;
            module->prev = current;
        } else {
            /* Insert between current->prev and current */
            if (current->prev != NULL) {
                current->prev->next = module;
            } else {
                bsp_module_manager.modules[module->config.type] = module;
            }
            module->prev = current->prev;
            module->next = current;
            current->prev = module;
        }
    }
    
    bsp_module_manager.module_count++;
    
    return HAL_OK;
}

/**
 * @brief 注销一个 BSP 模块
 * @param module: 指向模块结构体的指针
 * @retval HAL 状态码
 */
hal_ret_t bsp_module_unregister(bsp_module_t* module) {
    if (module == NULL) {
        return HAL_INVALID_PARAM;
    }
    
    /* Deinitialize module if it's initialized */
    if (module->state != BSP_MODULE_STATE_UNINIT) {
        if (module->ops.deinit != NULL) {
            module->ops.deinit();
        }
        module->state = BSP_MODULE_STATE_UNINIT;
    }
    
    /* Remove module from linked list */
    if (module->prev != NULL) {
        module->prev->next = module->next;
    } else {
        /* Module is first in the list */
        bsp_module_manager.module_list = module->next;
    }
    
    if (module->next != NULL) {
        module->next->prev = module->prev;
    }
    
    /* Remove module from type-specific list */
    if (bsp_module_manager.modules[module->config.type] == module) {
        bsp_module_manager.modules[module->config.type] = module->next;
    }
    
    /* Reset module pointers */
    module->next = NULL;
    module->prev = NULL;
    
    bsp_module_manager.module_count--;
    
    return HAL_OK;
}

/**
 * @brief 获取指定的 BSP 模块
 * @param type: 模块类型
 * @param instance: 模块实例
 * @retval 指向模块结构体的指针，未找到返回 NULL
 */
bsp_module_t* bsp_module_get(bsp_module_type_t type, uint8_t instance) {
    if (type >= BSP_MODULE_TYPE_MAX) {
        return NULL;
    }
    
    bsp_module_t* current = bsp_module_manager.modules[type];
    while (current != NULL && current->config.type == type) {
        if (current->config.instance == instance) {
            return current;
        }
        current = current->next;
    }
    
    return NULL;
}

/**
 * @brief 获取指定类型的所有模块
 * @param type: 模块类型
 * @retval 指向模块列表的指针，未找到模块返回 NULL
 */
bsp_module_t* bsp_module_get_by_type(bsp_module_type_t type) {
    if (type >= BSP_MODULE_TYPE_MAX) {
        return NULL;
    }
    
    return bsp_module_manager.modules[type];
}

/**
 * @brief 通过名称获取模块
 * @param name: 模块名称
 * @retval 指向模块结构体的指针，未找到返回 NULL
 */
bsp_module_t* bsp_module_get_by_name(const char* name) {
    if (name == NULL) {
        return NULL;
    }
    
    bsp_module_t* current = bsp_module_manager.module_list;
    while (current != NULL) {
        if (current->config.name != NULL && strcmp(current->config.name, name) == 0) {
            return current;
        }
        current = current->next;
    }
    
    return NULL;
}

/**
 * @brief 检查模块的所有依赖是否满足
 * @param module: 指向模块结构体的指针
 * @retval HAL 状态码
 */
hal_ret_t bsp_module_check_dependencies(const bsp_module_t* module) {
    if (module == NULL) {
        return HAL_INVALID_PARAM;
    }
    
    /* Check if dependencies are satisfied */
    if (module->config.dependencies == 0) {
        /* No dependencies */
        return HAL_OK;
    }
    
    /* Check each dependency bit */
    for (uint8_t i = 0; i < BSP_MODULE_TYPE_MAX; i++) {
        if (module->config.dependencies & (1 << i)) {
            /* Check if dependency module exists and is initialized */
            bsp_module_t* dep_module = bsp_module_manager.modules[i];
            if (dep_module == NULL) {
                return HAL_RET_ERROR;
            }
            
            /* Check if at least one instance is initialized */
            bsp_module_t* current = dep_module;
            uint8_t dep_found = 0;
            while (current != NULL && current->config.type == i) {
                if (current->state >= BSP_MODULE_STATE_INIT) {
                    dep_found = 1;
                    break;
                }
                current = current->next;
            }
            
            if (!dep_found) {
                return HAL_ERROR;
            }
        }
    }
    
    return HAL_OK;
}

/**
 * @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) {
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    /* Check if module is already initialized */
    if (module->state != BSP_MODULE_STATE_UNINIT) {
        return HAL_OK;
    }
    
    /* Check dependencies */
    hal_ret_t status = bsp_module_check_dependencies(module);
    if (status != HAL_OK) {
        module->state = BSP_MODULE_STATE_ERROR;
        return status;
    }
    
    /* Initialize module */
    if (module->ops.init != NULL) {
        status = module->ops.init(module->config.config_data);
        if (status != HAL_OK) {
            module->state = BSP_MODULE_STATE_ERROR;
            return status;
        }
    }
    
    module->state = BSP_MODULE_STATE_INIT;
    
    return HAL_OK;
}

/**
 * @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) {
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    /* Check if module is already uninitialized */
    if (module->state == BSP_MODULE_STATE_UNINIT) {
        return HAL_OK;
    }
    
    /* Stop module if it's running */
    if (module->state == BSP_MODULE_STATE_RUNNING && module->ops.stop != NULL) {
        module->ops.stop();
    }
    
    /* Deinitialize module */
    if (module->ops.deinit != NULL) {
        hal_ret_t status = module->ops.deinit();
        if (status != HAL_OK) {
            module->state = BSP_MODULE_STATE_ERROR;
            return status;
        }
    }
    
    module->state = BSP_MODULE_STATE_UNINIT;
    
    return HAL_OK;
}

/**
 * @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) {
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    /* Check if module is initialized */
    if (module->state < BSP_MODULE_STATE_INIT) {
        return HAL_ERROR;
    }
    
    /* Configure module */
    if (module->ops.configure != NULL) {
        hal_ret_t status = module->ops.configure(config);
        if (status != HAL_OK) {
            module->state = BSP_MODULE_STATE_ERROR;
            return status;
        }
    }
    
    module->state = BSP_MODULE_STATE_CONFIGURED;
    
    return HAL_OK;
}

/**
 * @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) {
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    /* Check if module is configured */
    if (module->state < BSP_MODULE_STATE_CONFIGURED) {
        return HAL_ERROR;
    }
    
    /* Start module */
    if (module->ops.start != NULL) {
        hal_ret_t status = module->ops.start();
        if (status != HAL_OK) {
            module->state = BSP_MODULE_STATE_ERROR;
            return status;
        }
    }
    
    module->state = BSP_MODULE_STATE_RUNNING;
    
    return HAL_OK;
}

/**
 * @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) {
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    /* Check if module is running */
    if (module->state != BSP_MODULE_STATE_RUNNING) {
        return HAL_OK;
    }
    
    /* Stop module */
    if (module->ops.stop != NULL) {
        hal_ret_t status = module->ops.stop();
        if (status != HAL_OK) {
            module->state = BSP_MODULE_STATE_ERROR;
            return status;
        }
    }
    
    module->state = BSP_MODULE_STATE_CONFIGURED;
    
    return HAL_OK;
}

/**
 * @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) {
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    /* Stop module if it's running */
    hal_ret_t status = bsp_module_stop(type, instance);
    if (status != HAL_OK) {
        return status;
    }
    
    /* Deinitialize module */
    status = bsp_module_deinit(type, instance);
    if (status != HAL_OK) {
        return status;
    }
    
    /* Reinitialize module */
    status = bsp_module_init(type, instance);
    if (status != HAL_OK) {
        return status;
    }
    
    /* Configure module */
    if (module->config.config_data != NULL) {
        status = bsp_module_configure(type, instance, module->config.config_data, module->config.config_size);
        if (status != HAL_OK) {
            return status;
        }
    }
    
    /* Start module */
    status = bsp_module_start(type, instance);
    if (status != HAL_OK) {
        return status;
    }
    
    return HAL_OK;
}

/**
 * @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) {
    if (state == NULL) {
        return HAL_INVALID_PARAM;
    }
    
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        *state = BSP_MODULE_STATE_UNINIT;
        return HAL_ERROR;
    }
    
    *state = module->state;
    
    return HAL_OK;
}

/**
 * @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) {
    /* Get module */
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    /* Check if module is initialized */
    if (module->state < BSP_MODULE_STATE_INIT) {
        return HAL_ERROR;
    }
    
    /* Control module */
    if (module->ops.control != NULL) {
        return module->ops.control(cmd, param);
    }
    
    return HAL_RET_NOT_SUPPORTED;
}

/**
 * @brief Initialize all registered BSP modules in priority order
 * @retval HAL status code
 */
hal_ret_t bsp_module_init_all(void) {
    hal_ret_t status = HAL_RET_OK;
    
    /* Initialize modules by priority */
    for (uint8_t priority = BSP_MODULE_PRIORITY_HIGHEST; priority <= BSP_MODULE_PRIORITY_LOWEST; priority++) {
        bsp_module_t* current = bsp_module_manager.module_list;
        while (current != NULL) {
            if (current->config.priority == priority) {
                status = bsp_module_init(current->config.type, current->config.instance);
                if (status != HAL_OK) {
                    return status;
                }
            }
            current = current->next;
        }
    }
    
    return status;
}

/**
 * @brief Deinitialize all registered BSP modules in reverse priority order
 * @retval HAL status code
 */
hal_ret_t bsp_module_deinit_all(void) {
    hal_status_t status = HAL_OK;
    
    /* Deinitialize modules by reverse priority */
    for (int8_t priority = BSP_MODULE_PRIORITY_LOWEST; priority >= BSP_MODULE_PRIORITY_HIGHEST; priority--) {
        bsp_module_t* current = bsp_module_manager.module_list;
        while (current != NULL) {
            if (current->config.priority == priority) {
                status = bsp_module_deinit(current->config.type, current->config.instance);
                if (status != HAL_OK) {
                    return status;
                }
            }
            current = current->next;
        }
    }
    
    return status;
}

/**
 * @brief Start all registered BSP modules in priority order
 * @retval HAL status code
 */
hal_ret_t bsp_module_start_all(void) {
    hal_status_t status = HAL_OK;
    
    /* Start modules by priority */
    for (uint8_t priority = BSP_MODULE_PRIORITY_HIGHEST; priority <= BSP_MODULE_PRIORITY_LOWEST; priority++) {
        bsp_module_t* current = bsp_module_manager.module_list;
        while (current != NULL) {
            if (current->config.priority == priority && current->state >= BSP_MODULE_STATE_CONFIGURED) {
                status = bsp_module_start(current->config.type, current->config.instance);
                if (status != HAL_OK) {
                    return status;
                }
            }
            current = current->next;
        }
    }
    
    return status;
}

/**
 * @brief Stop all registered BSP modules in reverse priority order
 * @retval HAL status code
 */
hal_ret_t bsp_module_stop_all(void) {
    hal_status_t status = HAL_OK;
    
    /* Stop modules by reverse priority */
    for (int8_t priority = BSP_MODULE_PRIORITY_LOWEST; priority >= BSP_MODULE_PRIORITY_HIGHEST; priority--) {
        bsp_module_t* current = bsp_module_manager.module_list;
        while (current != NULL) {
            if (current->config.priority == priority && current->state == BSP_MODULE_STATE_RUNNING) {
                status = bsp_module_stop(current->config.type, current->config.instance);
                if (status != HAL_OK) {
                    return status;
                }
            }
            current = current->next;
        }
    }
    
    return status;
}

/**
 * @brief Get total number of registered modules
 * @retval Number of registered modules
 */
uint32_t bsp_module_get_count(void) {
    return bsp_module_manager.module_count;
}

/**
 * @brief Get module manager instance
 * @retval Pointer to module manager structure
 */
bsp_module_manager_t* bsp_module_get_manager(void) {
    return &bsp_module_manager;
}

/**
 * @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) {
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    module->event_callback = callback;
    return HAL_OK;
}

/**
 * @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) {
    if (module == NULL) {
        return HAL_INVALID_PARAM;
    }
    
    // Check if module has an event callback registered
    if (module->event_callback != NULL) {
        return module->event_callback(module, event, data);
    }
    
    return HAL_OK;
}

/**
 * @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) {
    if (count == NULL) {
        return NULL;
    }
    
    // First pass: count matching modules
    uint32_t module_count = 0;
    bsp_module_t* current = bsp_module_manager.module_list;
    while (current != NULL) {
        if (current->config.priority >= min_priority && current->config.priority <= max_priority) {
            module_count++;
        }
        current = current->next;
    }
    
    if (module_count == 0) {
        *count = 0;
        return NULL;
    }
    
    // Second pass: allocate and fill array
    bsp_module_t** modules = (bsp_module_t**)malloc(module_count * sizeof(bsp_module_t*));
    if (modules == NULL) {
        *count = 0;
        return NULL;
    }
    
    uint32_t index = 0;
    current = bsp_module_manager.module_list;
    while (current != NULL && index < module_count) {
        if (current->config.priority >= min_priority && current->config.priority <= max_priority) {
            modules[index++] = current;
        }
        current = current->next;
    }
    
    *count = module_count;
    return modules;
}

/**
 * @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) {
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    module->config.enable = enable;
    return HAL_OK;
}

/**
 * @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) {
    if (enable == NULL) {
        return HAL_INVALID_PARAM;
    }
    
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        *enable = 0;
        return HAL_ERROR;
    }
    
    *enable = module->config.enable;
    return HAL_OK;
}

/**
 * @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) {
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        return HAL_ERROR;
    }
    
    module->config.priority = priority;
    return HAL_OK;
}

/**
 * @brief Get module priority
 * @param type: Module type
 * @param instance: Module instance
 * @param priority: Pointer to store priority
 * @retval HAL status code
 */
hal_ret_t bsp_module_get_priority(bsp_module_type_t type, uint8_t instance, bsp_module_priority_t* priority) {
    if (priority == NULL) {
        return HAL_INVALID_PARAM;
    }
    
    bsp_module_t* module = bsp_module_get(type, instance);
    if (module == NULL) {
        *priority = BSP_MODULE_PRIORITY_MEDIUM;
        return HAL_ERROR;
    }
    
    *priority = module->config.priority;
    return HAL_OK;
}