use std::sync::{Arc, mpsc};

pub fn info(message: &str) {
    println!("\x1b[32mINFO:\x1b[0m {message}");
}

#[derive(Debug)]
pub struct LogReceiver {
    logs_rx: mpsc::Receiver<String>,
    sender: Logger,
    use_stdio: bool,
}

#[derive(Debug, Clone)]
pub struct Logger {
    use_stdio: bool,
    logs_tx: Arc<mpsc::Sender<String>>,
}

impl Logger {
    #[must_use]
    pub fn new(logs_tx: mpsc::Sender<String>, use_stdio: bool) -> Self {
        Self {
            use_stdio,
            logs_tx: Arc::new(logs_tx),
        }
    }

    pub fn info(&self, message: &str) {
        let res = format!("\x1b[32mINFO:\x1b[0m {message}");
        if self.use_stdio {
            println!("{res}");
        }

        self.logs_tx.send(res).expect("Failed to send log message");
    }
}

impl LogReceiver {
    #[must_use]
    pub fn new(use_stdio: bool) -> Self {
        let (logs_tx, logs_rx) = mpsc::channel();
        Self {
            use_stdio,
            logs_rx,
            sender: Logger::new(logs_tx, use_stdio),
        }
    }

    #[must_use]
    pub fn logs(&self) -> Vec<String> {
        self.logs_rx.try_iter().collect()
    }

    #[must_use]
    pub fn logger(&self) -> Logger {
        self.sender.clone()
    }
}

impl Default for LogReceiver {
    fn default() -> Self {
        Self::new(true)
    }
}
