use {
    std::{
        io::Result,
        time::{Duration, Instant},
    },
    crossterm::{
        cursor,
        event::{Event, KeyCode, self},
        terminal::{
            EnterAlternateScreen,
            LeaveAlternateScreen,
            disable_raw_mode,
            enable_raw_mode,
        },
    },
};

mod args;
mod config;
mod display;
mod error;

fn main() -> Result <()> {
    let args = match args::parse_arguments() {
        Ok (o) => o,
        Err(e) => {
            eprintln!("{e}");
            std::process::exit(1);
        }
    };

    if args.help {
        println!("{}", args::help_string());
        return Ok(());
    }

    if args.version {
        println!("{}", args::version_string());
        return Ok(());
    }
    
    if args.list {
        display::print_fonts();
        return Ok(());
    }
    
    enable_raw_mode()?;
    crossterm::execute! {
        std::io::stdout(),
        EnterAlternateScreen,
        cursor::Hide
    }?;

    let cfg = config::Config::new(&args.font, &args.colors);
    let tick_rate = Duration::from_secs(1);

    if let Err(e) = display::print_time(&args, &cfg) {
        println!("{e}");
    }

    let mut last_tick = Instant::now();

    loop {
        let timeout = tick_rate.saturating_sub(last_tick.elapsed());
        if event::poll(timeout)? {
            if let Event::Key(q) = event::read()? {
                if args.screensaver | (q.code == KeyCode::Char('q')) { break; }
            }
        }

        if last_tick.elapsed() >= tick_rate {
            if let Err(e) = display::print_time(&args, &cfg) {
                println!("{e}");
            }
            last_tick = Instant::now();
        }
    }

    disable_raw_mode()?;
    crossterm::execute! {
        std::io::stdout(),
        LeaveAlternateScreen,
        cursor::Show
    }?;
    Ok(())
}
