use std::io::{self, BufWriter};
use std::path::PathBuf;

use clap::Args;
use obikindex::KmerIndex;
use obisys::progress_bar;
use tracing::info;

use super::predicate::FilterArgs;

#[derive(Args)]
pub struct DumpArgs {
    /// Index directory to dump
    pub index: PathBuf,

    /// Output presence/absence (0/1) even if the index stores counts
    #[arg(long, default_value_t = false)]
    pub force_presence: bool,

    /// Prepend partition and layer columns to each row
    #[arg(long, default_value_t = false)]
    pub debug: bool,

    /// Only output the first N kmers
    #[arg(long)]
    pub head: Option<usize>,

    #[command(flatten)]
    pub filter: FilterArgs,
}

pub fn run(args: DumpArgs) {
    let idx = KmerIndex::open(&args.index).unwrap_or_else(|e| {
        eprintln!("error opening index: {e}");
        std::process::exit(1);
    });

    info!(
        "dumping {} partitions, {} genome(s)",
        idx.n_partitions(),
        &idx.meta().genomes.len()
    );

    let filters = args.filter.build_filters(&idx.meta().genomes);
    let pb = progress_bar("dump", idx.n_partitions() as u64, "partitions");

    let stdout = io::stdout();
    let mut out = BufWriter::new(stdout.lock());

    idx.dump(&mut out, args.force_presence, args.debug, args.head, &filters, || pb.inc(1)).unwrap_or_else(|e| {
        eprintln!("dump error: {e}");
        std::process::exit(1);
    });
    pb.finish_and_clear();
}
