use std::path::PathBuf;

#[derive(Debug, PartialEq, Eq)]
pub(super) struct Args {
    pub(super) left_sequence: PathBuf,
    pub(super) right_sequence: PathBuf,
    pub(super) out_dir: PathBuf,
    pub(super) align_window_runs: u32,
    pub(super) align_window_secs: i64,
    pub(super) sample_limit: usize,
    pub(super) warmup_samples: usize,
    pub(super) cooldown_samples: usize,
    pub(super) timeline_sample_limit: usize,
}

pub(super) fn usage() -> &'static str {
    "Usage: sequence_triage_ccr_cir --left-sequence <path> --right-sequence <path> --out-dir <path> [--align-window-runs <n>] [--align-window-secs <n>] [--sample-limit <n>] [--warmup-samples <n>] [--cooldown-samples <n>] [--timeline-sample-limit <n>]"
}

pub(super) fn parse_args(argv: &[String]) -> Result<Args, String> {
    let mut left_sequence = None;
    let mut right_sequence = None;
    let mut out_dir = None;
    let mut align_window_runs = 2u32;
    let mut align_window_secs = 1800i64;
    let mut sample_limit = 200usize;
    let mut warmup_samples = 1usize;
    let mut cooldown_samples = 1usize;
    let mut timeline_sample_limit = 0usize;
    let mut index = 1usize;
    while index < argv.len() {
        match argv[index].as_str() {
            "--left-sequence" => {
                index += 1;
                left_sequence = Some(PathBuf::from(
                    argv.get(index).ok_or("--left-sequence requires a value")?,
                ));
            }
            "--right-sequence" => {
                index += 1;
                right_sequence = Some(PathBuf::from(
                    argv.get(index).ok_or("--right-sequence requires a value")?,
                ));
            }
            "--out-dir" => {
                index += 1;
                out_dir = Some(PathBuf::from(
                    argv.get(index).ok_or("--out-dir requires a value")?,
                ));
            }
            "--align-window-runs" => {
                index += 1;
                let value = argv
                    .get(index)
                    .ok_or("--align-window-runs requires a value")?;
                align_window_runs = value
                    .parse::<u32>()
                    .map_err(|_| format!("invalid --align-window-runs: {value}"))?;
            }
            "--align-window-secs" => {
                index += 1;
                let value = argv
                    .get(index)
                    .ok_or("--align-window-secs requires a value")?;
                align_window_secs = value
                    .parse::<i64>()
                    .map_err(|_| format!("invalid --align-window-secs: {value}"))?;
            }
            "--sample-limit" => {
                index += 1;
                let value = argv.get(index).ok_or("--sample-limit requires a value")?;
                sample_limit = value
                    .parse::<usize>()
                    .map_err(|_| format!("invalid --sample-limit: {value}"))?;
            }
            "--warmup-samples" => {
                index += 1;
                let value = argv.get(index).ok_or("--warmup-samples requires a value")?;
                warmup_samples = value
                    .parse::<usize>()
                    .map_err(|_| format!("invalid --warmup-samples: {value}"))?;
            }
            "--cooldown-samples" => {
                index += 1;
                let value = argv
                    .get(index)
                    .ok_or("--cooldown-samples requires a value")?;
                cooldown_samples = value
                    .parse::<usize>()
                    .map_err(|_| format!("invalid --cooldown-samples: {value}"))?;
            }
            "--timeline-sample-limit" => {
                index += 1;
                let value = argv
                    .get(index)
                    .ok_or("--timeline-sample-limit requires a value")?;
                timeline_sample_limit = value
                    .parse::<usize>()
                    .map_err(|_| format!("invalid --timeline-sample-limit: {value}"))?;
            }
            "-h" | "--help" => return Err(usage().to_string()),
            other => return Err(format!("unknown argument: {other}\n{}", usage())),
        }
        index += 1;
    }
    Ok(Args {
        left_sequence: left_sequence
            .ok_or_else(|| format!("--left-sequence is required\n{}", usage()))?,
        right_sequence: right_sequence
            .ok_or_else(|| format!("--right-sequence is required\n{}", usage()))?,
        out_dir: out_dir.ok_or_else(|| format!("--out-dir is required\n{}", usage()))?,
        align_window_runs,
        align_window_secs,
        sample_limit,
        warmup_samples,
        cooldown_samples,
        timeline_sample_limit,
    })
}
