Documentation
use clap::Args;

use liwe::model::Key;
use liwe::selector::{KeyDepth, Selector};

#[derive(Debug, Args, Clone, Default)]
pub struct SelectorArgs {
    #[clap(
        long = "in",
        value_parser = parse_key_depth,
        help = "Restrict to sub-documents of EVERY listed key (AND). Use KEY or KEY:DEPTH. Repeat for multiple."
    )]
    pub in_: Vec<KeyDepth>,

    #[clap(
        long = "in-any",
        value_parser = parse_key_depth,
        help = "Restrict to sub-documents of AT LEAST ONE listed key (OR). Use KEY or KEY:DEPTH."
    )]
    pub in_any: Vec<KeyDepth>,

    #[clap(
        long = "not-in",
        value_parser = parse_key_depth,
        help = "Exclude sub-documents of any listed key (NOT). Use KEY or KEY:DEPTH."
    )]
    pub not_in: Vec<KeyDepth>,

    #[clap(
        long = "max-depth",
        help = "Default depth applied to in / in-any / not-in entries without their own depth. Omit for unbounded."
    )]
    pub max_depth: Option<u8>,
}

impl From<SelectorArgs> for Selector {
    fn from(args: SelectorArgs) -> Self {
        Selector {
            in_: args.in_,
            in_any: args.in_any,
            not_in: args.not_in,
            max_depth: args.max_depth,
        }
    }
}

fn parse_key_depth(s: &str) -> Result<KeyDepth, String> {
    if let Some((k, d)) = s.rsplit_once(':') {
        let depth: u8 = d
            .parse()
            .map_err(|_| format!("invalid depth in '{}': expected non-negative integer", s))?;
        Ok(KeyDepth::with_depth(Key::name(k), depth))
    } else {
        Ok(KeyDepth::bare(Key::name(s)))
    }
}