pub mod command;
pub mod errors;

use command::*;
use errors::*;

use clap::Parser;
use std::fmt::Display;
use std::io;
use std::path::PathBuf;

#[derive(Parser)]
pub struct Opt {
    #[arg(hide = true)] // TODO: hidden option for debug? or usefull for everyone?
    pub config_folder: Option<PathBuf>,

    #[arg(short, long)]
    pub quiet: bool, // TODO: use clap_verbosity_flag instead

    #[arg(short, long)]
    pub steps: Vec<UpdateSteps>,
}

pub struct Record {
    packager: String,
    executor: String,
    status: Status,
}
impl Display for Record {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "\t{} ({})\t{}",
            &self.packager, &self.executor, &self.status
        )
    }
}

pub struct Summary {
    status: Vec<Record>,
}

impl Display for Summary {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f)?;
        writeln!(f, "*** Summary: ***")?;
        for record in &self.status {
            // TODO: also print version before/after, update time

            writeln!(f, "{record}")?;
        }
        Ok(())
    }
}

pub fn run(opt: &Opt) -> io::Result<Summary> {
    let updater = Updater::from_config(opt)?;

    if updater.packagers.is_empty() {
        let package_folder = get_packages_folder(opt)?;
        return Err(io::Error::new(
            io::ErrorKind::Other,
            format!(
                r#"No package found in configuration folder. Add them in: '{}'
Here is a folder with example you can download: https://framagit.org/Zykino/system-updater/-/tree/v{}/example_packagers"#,
                package_folder.display(),
                env!("CARGO_PKG_VERSION")
            ),
        ));
    }

    Ok(updater.update_all(opt))
}
