use log::LevelFilter;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Debug, Deserialize)]
pub enum LogLevel {
    /// A level lower than all log levels.
    Off,
    /// Corresponds to the `Error` log level.
    Error,
    /// Corresponds to the `Warn` log level.
    Warn,
    /// Corresponds to the `Info` log level.
    Info,
    /// Corresponds to the `Debug` log level.
    Debug,
    /// Corresponds to the `Trace` log level.
    Trace,
}

#[derive(Serialize, Debug, Deserialize)]
pub struct KernelConfig {
    pub logging: LoggingConfig,
}

impl KernelConfig {
    pub fn new() -> Self {
        KernelConfig::default()
    }
    pub fn load_from_string(toml_string: &str) -> Self {
        match toml::from_str(toml_string) {
            Ok(kernel_conf) => kernel_conf,
            Err(err) => {
                error!("Error {}", err);
                KernelConfig::new()
            }
        }
    }
    pub fn log_level(&self) -> LevelFilter {
        use LevelFilter::*;
        match self.logging.level {
            LogLevel::Off => Off,
            LogLevel::Error => Error,
            LogLevel::Warn => Warn,
            LogLevel::Info => Info,
            LogLevel::Debug => Debug,
            LogLevel::Trace => Trace,
        }
    }
}

impl Default for KernelConfig {
    fn default() -> Self {
        Self {
            logging: LoggingConfig {
                enabled: true,
                log_to_serial: true,
                log_to_vterm: false,
                level: LogLevel::Trace,
                filter: Vec::new(),
            },
        }
    }
}

#[derive(Serialize, Debug, Deserialize)]
pub struct LoggingConfig {
    pub enabled: bool,
    pub log_to_serial: bool,
    pub log_to_vterm: bool,
    pub level: LogLevel,
    pub filter: Vec<String>,
}
