use super::interface::LogLine;
use log::{Log, Metadata, Record};
use once_cell::sync::Lazy;
use std::sync::{Arc, RwLock};

#[derive(Debug)]
pub(crate) struct TestLogger {
    pub(crate) lines: Lazy<Arc<RwLock<Vec<LogLine>>>>,
}

impl Log for TestLogger {
    fn enabled(&self, _: &Metadata) -> bool {
        true
    }

    fn log(&self, record: &Record) {
        self.lines
            .write()
            .unwrap()
            .push(LogLine(record.level(), format!("{}", record.args())));
    }

    fn flush(&self) {
        // Do nothing
    }
}

#[cfg(test)]
mod tests {
    use super::TestLogger;
    use crate::{assert_contains_exactly, logging::interface::LogLine};
    use log::{Level, Log, RecordBuilder};
    use once_cell::sync::Lazy;
    use std::sync::{Arc, RwLock};

    #[test]
    fn should_record_log_lines() {
        let logger = TestLogger {
            lines: Lazy::new(|| Arc::new(RwLock::new(Vec::new()))),
        };

        logger.log(
            &RecordBuilder::new()
                .level(Level::Info)
                .args(format_args!("Info"))
                .build(),
        );

        assert_contains_exactly!(
            logger.lines.read().unwrap(),
            vec![LogLine(Level::Info, "Info".to_string())]
        );
    }
}
