/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : hal.h
  * @brief          : Hardware Abstraction Layer common header file
  ******************************************************************************
  */
/* USER CODE END Header */

#ifndef HAL_H
#define HAL_H

#include <stdint.h>

/* HAL version definitions */
#define HAL_VERSION_MAJOR 1
#define HAL_VERSION_MINOR 0
#define HAL_VERSION_PATCH 0
#define HAL_VERSION_STRING "1.0.0"

/* Define supported architectures */
#define HAL_ARCH_STM32F1 0
#define HAL_ARCH_STM32F4 1
#define HAL_ARCH_STM32F7 2
#define HAL_ARCH_STM32L4 3

/* Select target architecture */
#ifndef HAL_TARGET_ARCH
#define HAL_TARGET_ARCH HAL_ARCH_STM32F4
#endif

/* Architecture specific functions will be included in implementation files */

/* Architecture compatibility check */
#if HAL_TARGET_ARCH < HAL_ARCH_STM32F1 || HAL_TARGET_ARCH > HAL_ARCH_STM32L4
#error "Invalid HAL architecture selection"
#endif

/**
 * @brief HAL status return codes - renamed to avoid conflict with STM32 HAL
 */
typedef enum {
    HAL_RET_OK                 = 0x00U,    /*!< Operation completed successfully */
    HAL_RET_ERROR              = 0x01U,    /*!< Generic operation failed */
    HAL_RET_BUSY               = 0x02U,    /*!< Peripheral or resource busy */
    HAL_RET_TIMEOUT            = 0x03U,    /*!< Operation timed out */
    HAL_RET_INVALID_PARAM      = 0x04U,    /*!< Invalid parameter */
    HAL_RET_NOT_SUPPORTED      = 0x05U,    /*!< Operation not supported */
    HAL_RET_OUT_OF_MEMORY      = 0x06U,    /*!< Out of memory */
    HAL_RET_INTERNAL_ERROR     = 0x07U,    /*!< Internal error */
    HAL_RET_RESOURCE_LOCKED    = 0x08U,    /*!< Resource locked */
    HAL_RET_RESOURCE_ERROR     = 0x09U,    /*!< Resource error */
    HAL_RET_COMM_ERROR         = 0x0AU,    /*!< Communication error */
    HAL_RET_CONFIG_ERROR       = 0x0BU,    /*!< Configuration error */
    HAL_RET_INIT_ERROR         = 0x0CU,    /*!< Initialization error */
    HAL_RET_DEINIT_ERROR       = 0x0DU,    /*!< Deinitialization error */
    HAL_RET_IO_ERROR           = 0x0EU,    /*!< I/O operation error */
    HAL_RET_OVERRUN_ERROR      = 0x0FU,    /*!< Overrun error */
    HAL_RET_UNDERRUN_ERROR     = 0x10U,    /*!< Underrun error */
    HAL_RET_PARITY_ERROR       = 0x11U,    /*!< Parity error */
    HAL_RET_FRAMING_ERROR      = 0x12U,    /*!< Framing error */
    HAL_RET_NOISE_ERROR        = 0x13U     /*!< Noise error */
} hal_ret_t;

/**
 * @brief HAL error category definitions
 */
typedef enum {
    HAL_ERR_CAT_COMMON      = 0x00U,    /*!< Common error category */
    HAL_ERR_CAT_GPIO        = 0x10U,    /*!< GPIO error category */
    HAL_ERR_CAT_UART        = 0x20U,    /*!< UART error category */
    HAL_ERR_CAT_SPI         = 0x30U,    /*!< SPI error category */
    HAL_ERR_CAT_I2C         = 0x40U,    /*!< I2C error category */
    HAL_ERR_CAT_CAN         = 0x50U,    /*!< CAN error category */
    HAL_ERR_CAT_ADC         = 0x60U,    /*!< ADC error category */
    HAL_ERR_CAT_DMA         = 0x70U,    /*!< DMA error category */
    HAL_ERR_CAT_RTC         = 0x80U,    /*!< RTC error category */
    HAL_ERR_CAT_MODULE      = 0x90U,    /*!< Module management error category */
    HAL_ERR_CAT_ARCH        = 0xA0U,    /*!< Architecture specific error category */
    HAL_ERR_CAT_MAX         = 0xFFU     /*!< Maximum error category */
} hal_error_category_t;

/**
 * @brief HAL extended error code structure
 */
typedef struct {
    hal_ret_t status;               /*!< HAL status code */
    hal_error_category_t category;     /*!< Error category */
    uint32_t specific_error;           /*!< Specific error code (category dependent) */
    const char* file;                  /*!< File where error occurred */
    uint32_t line;                     /*!< Line number where error occurred */
    const char* function;              /*!< Function where error occurred */
    uint32_t timestamp;                /*!< Error timestamp */
} hal_error_t;

/**
 * @brief HAL error callback type
 */
typedef void (*hal_error_callback_t)(const hal_error_t* error);

/**
 * @brief HAL error information context
 */
typedef struct {
    hal_error_callback_t callback;     /*!< Error callback function */
    hal_error_t last_error;            /*!< Last error information */
    uint32_t error_count;              /*!< Total error count */
    uint8_t enabled;                   /*!< Error logging enabled flag */
} hal_error_context_t;

/**
 * @brief HAL module types
 */
typedef enum {
    HAL_MODULE_GPIO = 0,
    HAL_MODULE_UART,
    HAL_MODULE_SPI,
    HAL_MODULE_I2C,
    HAL_MODULE_CAN,
    HAL_MODULE_ADC,
    HAL_MODULE_DAC,
    HAL_MODULE_TIMER,
    HAL_MODULE_RTC,
    HAL_MODULE_DMA,
    HAL_MODULE_MAX
} hal_module_type_t;

/**
 * @brief HAL handle structure - base for all HAL peripherals
 */
typedef struct {
    void* instance;
    void* config;
    hal_ret_t status;
    uint32_t lock;
    void* user_data;
} hal_handle_t;

/**
 * @brief HAL module operations structure - unified API for all modules
 */
typedef struct {
    hal_ret_t (*init)(hal_handle_t* handle);
    hal_ret_t (*deinit)(hal_handle_t* handle);
    hal_ret_t (*configure)(hal_handle_t* handle, void* config);
    hal_ret_t (*control)(hal_handle_t* handle, uint32_t cmd, void* param);
    hal_ret_t (*get_status)(hal_handle_t* handle, uint32_t* status);
} hal_module_ops_t;

/**
 * @brief HAL module configuration structure
 */
typedef struct {
    hal_module_type_t type;
    const char* name;
    uint32_t version;
    hal_module_ops_t ops;
    void* default_config;
} hal_module_config_t;

/**
 * @brief HAL initialization structure
 */
typedef struct {
    uint32_t module_count;
    const hal_module_config_t* modules;
    uint32_t flags;
} hal_init_t;

/**
 * @brief HAL flags definitions
 */
#define HAL_INIT_FLAG_DEBUG       (1 << 0)  /*!< Enable debug mode */
#define HAL_INIT_FLAG_NO_CACHE    (1 << 1)  /*!< Disable cache */
#define HAL_INIT_FLAG_SAFE_MODE   (1 << 2)  /*!< Enable safe mode */

/**
 * @brief HAL peripheral state definitions
 */
typedef enum {
    HAL_PERIPH_STATE_RESET = 0,
    HAL_PERIPH_STATE_READY,
    HAL_PERIPH_STATE_BUSY,
    HAL_PERIPH_STATE_TIMEOUT,
    HAL_PERIPH_STATE_ERROR
} hal_periph_state_t;

/**
 * @brief HAL lock/unlock macros
 */
#define HAL_LOCK(handle)   do { while((handle)->lock); (handle)->lock = 1; } while(0)
#define HAL_UNLOCK(handle) do { (handle)->lock = 0; } while(0)

/**
 * @brief HAL handle initialization macro
 */
#define HAL_HANDLE_INIT(handle) \
    do { \
        memset((handle), 0, sizeof(hal_handle_t)); \
        (handle)->status = HAL_RET_OK; \
        (handle)->lock = 0; \
    } while(0)

/**
 * @brief HAL module registration macro
 */
#define HAL_MODULE_REGISTER(module) \
    static const hal_module_config_t __hal_module_##module##_config = { \
        .type = HAL_MODULE_##module, \
        .name = #module, \
        .version = 1, \
        .ops = __hal_##module##_ops, \
        .default_config = &__hal_##module##_default_config \
    };

/**
 * @brief HAL module registration at startup
 */
#define HAL_MODULE_REGISTER_STARTUP(module) \
    HAL_MODULE_REGISTER(module) \
    __attribute__((constructor)) static void __hal_register_##module##_at_startup(void) { \
        hal_module_register(&__hal_module_##module##_config); \
    }

/**
 * @brief HAL module initialization
 */
hal_ret_t hal_init(void);

/**
 * @brief Register a HAL module
 * @param module_config: Module configuration
 * @retval HAL status code
 */
hal_ret_t hal_module_register(const hal_module_config_t* module_config);

/**
 * @brief Initialize a specific HAL module
 * @param module_type: Module type
 * @param handle: HAL handle for the module
 * @retval HAL status code
 */
hal_ret_t hal_module_init(hal_module_type_t module_type, hal_handle_t* handle);

/**
 * @brief Deinitialize a specific HAL module
 * @param module_type: Module type
 * @param handle: HAL handle for the module
 * @retval HAL status code
 */
hal_ret_t hal_module_deinit(hal_module_type_t module_type, hal_handle_t* handle);

/**
 * @brief Configure a specific HAL module
 * @param module_type: Module type
 * @param handle: HAL handle for the module
 * @param config: Module configuration data
 * @retval HAL status code
 */
hal_ret_t hal_module_configure(hal_module_type_t module_type, hal_handle_t* handle, void* config);

/**
 * @brief Control a specific HAL module
 * @param module_type: Module type
 * @param handle: HAL handle for the module
 * @param cmd: Control command
 * @param param: Control parameter
 * @retval HAL status code
 */
hal_ret_t hal_module_control(hal_module_type_t module_type, hal_handle_t* handle, uint32_t cmd, void* param);

/**
 * @brief Get status of a specific HAL module
 * @param module_type: Module type
 * @param handle: HAL handle for the module
 * @param status: Pointer to store module status
 * @retval HAL status code
 */
hal_ret_t hal_module_get_status(hal_module_type_t module_type, hal_handle_t* handle, uint32_t* status);

/**
 * @brief Get default configuration for a module
 * @param module_type: Module type
 * @return Pointer to default configuration, or NULL if not available
 */
void* hal_module_get_default_config(hal_module_type_t module_type);

/**
 * @brief Get HAL version information
 * @param major: Pointer to store major version
 * @param minor: Pointer to store minor version
 * @param patch: Pointer to store patch version
 * @retval HAL status code
 */
hal_ret_t hal_get_version(uint8_t* major, uint8_t* minor, uint8_t* patch);

/**
 * @brief Get HAL version string
 * @retval Version string
 */
const char* hal_get_version_string(void);

/**
 * @brief Get HAL module count
 * @retval Number of registered HAL modules
 */
uint32_t hal_get_module_count(void);

/**
 * @brief Get HAL module configuration
 * @param module_type: Module type
 * @retval Pointer to module configuration, or NULL if not found
 */
const hal_module_config_t* hal_get_module_config(hal_module_type_t module_type);

/**
 * @brief Initialize HAL error handling system
 * @retval HAL status code
 */
hal_ret_t hal_error_init(void);

/**
 * @brief Deinitialize HAL error handling system
 * @retval HAL status code
 */
hal_ret_t hal_error_deinit(void);

/**
 * @brief Register an error callback function
 * @param callback: Error callback function
 * @retval HAL status code
 */
hal_ret_t hal_error_register_callback(hal_error_callback_t callback);

/**
 * @brief Record an error
 * @param error: Pointer to error information
 * @retval HAL status code
 */
hal_ret_t hal_error_record(const hal_error_t* error);

/**
 * @brief Get last error information
 * @retval Pointer to last error information
 */
const hal_error_t* hal_error_get_last(void);

/**
 * @brief Get total error count
 * @retval Total error count
 */
uint32_t hal_error_get_count(void);

/**
 * @brief Clear error information
 * @retval HAL status code
 */
hal_ret_t hal_error_clear(void);

/**
 * @brief Enable/disable error logging
 * @param enable: Enable flag (1 to enable, 0 to disable)
 * @retval HAL status code
 */
hal_ret_t hal_error_enable(uint8_t enable);

#endif /* HAL_H */
