use colored::{self, Colorize};
use chrono::prelude::*;
use std::sync::{Arc, Mutex};
use std::fs::File;
use std::io::Write;
#[derive(Debug, PartialEq)]
pub enum LogLevel{
DEBUG,
INFO,
WARNING,
ERROR,
}
pub struct Logger{
message_buffer: Arc<Mutex<Vec<String>>>,
output_lock: Arc<Mutex<()>>,
file_lock: Arc<Mutex<()>>,
}
impl Logger {
pub fn new() -> Self{
Logger{
message_buffer: Arc::new(Mutex::new(Vec::new())),
output_lock: Arc::new(Mutex::new(())),
file_lock: Arc::new(Mutex::new(())),
}
}
pub async fn log(&mut self, log_level: LogLevel, message: &str) -> std::io::Result<()>{
let output_log = self.output_lock.lock().unwrap();
let formatted_output = format!("[{}] [{:?}] {}", Local::now(), log_level, message);
if log_level == LogLevel::ERROR{
println!("{}", formatted_output.as_str().bright_red());
}else if log_level == LogLevel::WARNING {
println!("{}", formatted_output.as_str().bright_yellow());
}
else {
println!("{}", formatted_output.as_str().bright_white());
}
drop(output_log);
let mut buffer = self.message_buffer.lock().unwrap();
buffer.push(message.to_string());
Ok(())
}
pub async fn log_to_file(&mut self, log_level: LogLevel, message: &str, filename: &str) -> std::io::Result<()>{
let file_lock = self.file_lock.lock().unwrap();
let mut file = File::create(filename).unwrap();
let formatted_output = format!("[{}] [{:?}] {}", Local::now(), log_level, message);
writeln!(&mut file, "{}", formatted_output)?;
drop(file_lock);
let mut buffer = self.message_buffer.lock().unwrap();
buffer.push(message.to_string());
Ok(())
}
}