use std::path::PathBuf;

use clap::Parser;
use log::*;

use copytree::{Copier, CopyError, backend};

/// Copy file trees.
#[derive(Parser, Debug)]
#[command(name = "copytree", version)]
struct CopyTreeCLI {
    /// Suppress informational output
    #[arg(short = 'q', long = "quiet")]
    quiet: bool,
    /// Increase logging verbosity (can be repeated)
    #[arg(short='v', long="verbose", action=clap::ArgAction::Count)]
    verbose: u8,

    /// Follow symbolic links when traversing and copying
    #[arg(short = 'L', long = "follow")]
    follow_symlinks: bool,

    /// Include hidden files
    #[arg(short = 'H', long = "hidden")]
    include_hidden: bool,

    /// Do not respect ignore files
    #[arg(short = 'I', long = "no-ignore")]
    no_ignore: bool,

    /// Exclude files matching glob
    #[arg(short = 'E', long = "exclude")]
    exclude: Vec<String>,

    /// Delete target files missing from source.
    #[arg(long = "delete")]
    delete: bool,

    /// Source path
    src: PathBuf,
    /// Destination path
    dst: Option<PathBuf>,
}

impl CopyTreeCLI {
    fn init_logging(&self) -> Result<(), SetLoggerError> {
        let mut verbose: usize = 2;
        if self.verbose > 0 {
            verbose += self.verbose as usize;
        } else if self.quiet {
            verbose -= 1;
        }

        stderrlog::new().verbosity(verbose).init()?;
        Ok(())
    }
}

fn main() -> Result<(), CopyError> {
    let cli = CopyTreeCLI::parse();
    cli.init_logging().expect("logging setup failed");

    let mut src = backend::fs::FS::create(&cli.src);
    src.follow_symlinks(cli.follow_symlinks);
    src.include_hidden(cli.include_hidden);
    src.respect_ignore(!cli.no_ignore);
    for exc in &cli.exclude {
        src.exclude(exc);
    }

    let copy = Copier::new();

    if let Some(dst) = &cli.dst {
        let mut dst = backend::fs::FS::create(dst);
        dst.delete_extra(cli.delete);
        debug!("starting copy");

        copy.copy(&src, &dst)?;
    } else {
        let dst = backend::null::Null::create();
        copy.copy(&src, &dst)?;
    };

    Ok(())
}
