/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : logging.c
  * @brief          : Logging middleware source file
  ******************************************************************************
  */
/* USER CODE END Header */

#include "logging.h"
#include "uart.h"
#include <stdarg.h>

/* Current logging level */
static log_level_t current_level = LOG_LEVEL_INFO;

/**
 * @brief Get log level string
 * @param level: Log level
 * @retval Log level string
 */
static const char* log_level_to_string(log_level_t level) {
    switch (level) {
        case LOG_LEVEL_DEBUG:
            return "DEBUG";
        case LOG_LEVEL_INFO:
            return "INFO";
        case LOG_LEVEL_WARN:
            return "WARN";
        case LOG_LEVEL_ERROR:
            return "ERROR";
        case LOG_LEVEL_FATAL:
            return "FATAL";
        default:
            return "UNKNOWN";
    }
}

/**
 * @brief Initialize logging module
 */
void logging_init(void) {
    /* Initialize UART module */
    uart_init();
    
    /* Set default log level */
    current_level = LOG_LEVEL_INFO;
    
    /* Log initialization message */
    log_info("Logging module initialized\r\n");
}

/**
 * @brief Set logging level
 * @param level: Logging level to set
 */
void logging_set_level(log_level_t level) {
    current_level = level;
    log_info("Log level set to %s\r\n", log_level_to_string(level));
}

/**
 * @brief Get current logging level
 * @retval Current logging level
 */
log_level_t logging_get_level(void) {
    return current_level;
}

/**
 * @brief Internal log function
 * @param level: Log level
 * @param format: Format string
 * @param args: Variable arguments
 */
static void log_internal(log_level_t level, const char *format, va_list args) {
    char buffer[256];
    int ret;
    
    /* Check if log level is enabled */
    if (level < current_level || level >= LOG_LEVEL_NONE) {
        return;
    }
    
    /* Format log message */
    ret = snprintf(buffer, sizeof(buffer), "[%s] ", log_level_to_string(level));
    if (ret < 0 || (size_t)ret >= sizeof(buffer)) {
        return;
    }
    
    /* Append formatted message */
    ret = vsnprintf(buffer + ret, sizeof(buffer) - ret, format, args);
    if (ret < 0 || ret >= (int)(sizeof(buffer) - ret)) {
        return;
    }
    
    /* Send log message over UART */
    uart_send_string(buffer);
}

/**
 * @brief Log debug message
 * @param format: Format string
 * @param ...: Variable arguments
 */
void log_debug(const char *format, ...) {
    va_list args;
    va_start(args, format);
    log_internal(LOG_LEVEL_DEBUG, format, args);
    va_end(args);
}

/**
 * @brief Log info message
 * @param format: Format string
 * @param ...: Variable arguments
 */
void log_info(const char *format, ...) {
    va_list args;
    va_start(args, format);
    log_internal(LOG_LEVEL_INFO, format, args);
    va_end(args);
}

/**
 * @brief Log warning message
 * @param format: Format string
 * @param ...: Variable arguments
 */
void log_warn(const char *format, ...) {
    va_list args;
    va_start(args, format);
    log_internal(LOG_LEVEL_WARN, format, args);
    va_end(args);
}

/**
 * @brief Log error message
 * @param format: Format string
 * @param ...: Variable arguments
 */
void log_error(const char *format, ...) {
    va_list args;
    va_start(args, format);
    log_internal(LOG_LEVEL_ERROR, format, args);
    va_end(args);
}

/**
 * @brief Log fatal message
 * @param format: Format string
 * @param ...: Variable arguments
 */
void log_fatal(const char *format, ...) {
    va_list args;
    va_start(args, format);
    log_internal(LOG_LEVEL_FATAL, format, args);
    va_end(args);
}