/*
 * Copyright (c) 2022, Able <able@ablecorp.us>
 *
 * SPDX-License-Identifier: MPL-2.0
 */

use crate::{kmain::KERNEL_CONF, time::fetch_time};
use lliw::Fg;
use log::{Level, LevelFilter, Metadata, Record, SetLoggerError};

static LOGGER: SimpleLogger = SimpleLogger;
// TODO: Rebuild this to take advantage of sockets
// DETAIL: Log to a socket instead of the screen
// So that we can log in the kernel and display it in userland
struct SimpleLogger;
impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= Level::Trace
    }
    fn log(&self, record: &Record) {
        x86_64::instructions::interrupts::without_interrupts(|| {
            if self.enabled(record.metadata()) {
                let time_float = fetch_time();
                use Fg::*;

                let color = match record.level() {
                    log::Level::Error => (Fg::Red, "\0RED\0"),
                    log::Level::Warn => (Fg::LightYellow, "\0LIGHTYELLOW\0"),
                    log::Level::Info => (Fg::LightWhite, "\0LIGHTGREY\0"),
                    log::Level::Debug => (Fg::Blue, "\0BLUE\0"),
                    log::Level::Trace => (Fg::Yellow, "\0YELLOW\0"),
                };

                let mod_path = match record.module_path() {
                    Some(p) => {
                        if KERNEL_CONF.logging.filter.contains(&p.to_string()) {
                            return;
                        }

                        p
                    }
                    None => "unknown",
                };

                let line = match record.line() {
                    Some(line_number) => line_number,
                    None => 0,
                };

                if KERNEL_CONF.logging.log_to_vterm {
                    let msg = format!(
                        // "[{}{}$RESET$][$GREEN${}$RESET$]{}\n",
                        "[{}{:05}\0RESET\0][\0GREEN\0{}\0RESET\0][\0BLUE\0{}@{}\0RESET\0] {}",
                        color.1,
                        record.level(),
                        time_float,
                        mod_path,
                        line,
                        record.args(),
                    );

                    println!("{msg}");
                }

                if KERNEL_CONF.logging.log_to_serial {
                    serial_println!(
                        "[{}{:05}{}][{}{}{}][{}{}@{}{}] {}",
                        color.0,
                        record.level(),
                        Reset,
                        Green,
                        time_float,
                        Reset,
                        Blue,
                        mod_path,
                        line,
                        Reset,
                        record.args()
                    );
                }
            }
        });
    }
    /// Clear the log buffer
    fn flush(&self) {}
}

pub fn init() -> Result<(), SetLoggerError> {
    log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Trace))
    // ?;

    // trace!("Logger started");

    // Ok(())
}
