#![deny(clippy::all, clippy::nursery, clippy::pedantic, clippy::cargo)]
#![allow(clippy::default_trait_access, unused_doc_comments)]

mod commands;
mod parsing;

use std::error::Error;

use argh::FromArgs;

use crate::commands::{
    add,
    backup,
    block,
    check,
    config,
    edit,
    format,
    remove,
    search,
    show,
    stats,
    sync,
    unblock,
    uninstall,
    update,
    validate,
};

fn main() {
    if let Err(error) = run() {
        eprintln!("{}", error);
        std::process::exit(1);
    }
}

/// # Errors
///
/// Bad things often happen.
fn run() -> Result<(), Box<dyn Error>> {
    let args: Args = argh::from_env();
    match args.subcommand {
        SubCommand::Add(args) => {
            add::main(&args)?;
        }

        SubCommand::Backup(args) => {
            backup::main(&args)?;
        }

        SubCommand::Block(args) => {
            block::main(&args)?;
        }

        SubCommand::Check(args) => {
            check::main(&args)?;
        }

        SubCommand::Config(args) => {
            config::main(&args)?;
        }

        SubCommand::Delete(args) => {
            remove::main(&args)?;
        }

        SubCommand::Edit(args) => {
            edit::main(&args)?;
        }

        SubCommand::Format(args) => {
            format::main(&args)?;
        }

        SubCommand::Search(args) => {
            search::main(&args)?;
        }

        SubCommand::Show(args) => {
            show::main(&args)?;
        }

        SubCommand::Stats(args) => {
            stats::main(&args)?;
        }

        SubCommand::Sync(args) => {
            sync::main(&args)?;
        }

        SubCommand::Unblock(args) => {
            unblock::main(&args)?;
        }

        SubCommand::Uninstall(args) => {
            uninstall::main(&args)?;
        }

        SubCommand::Update(args) => {
            update::main(&args)?;
        }

        SubCommand::Validate(args) => {
            validate::main(&args);
        }
    }

    Ok(())
}

/// A CLI for manipulating hosts files
#[derive(FromArgs, PartialEq, Debug)]
struct Args {
    #[argh(subcommand)]
    subcommand: SubCommand,

    /// enable debug logging
    #[argh(switch, short = 'v')]
    verbose: bool,

    /// silence all output
    #[argh(switch, short = 'q')]
    quiet: bool,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum SubCommand {
    Add(add::Args),
    Backup(backup::Args),
    Block(block::Args),
    Check(check::Args),
    Config(config::Args),
    Delete(remove::Args),
    Edit(edit::Args),
    Format(format::Args),
    Search(search::Args),
    Show(show::Args),
    Stats(stats::Args),
    Sync(sync::Args),
    Unblock(unblock::Args),
    Uninstall(uninstall::Args),
    Update(update::Args),
    Validate(validate::Args),
}
