use std::collections::HashMap;
use crate::{
api::rest::{FullLabel, Label},
interactive,
};
use color_eyre::{Result, eyre::eyre};
use crate::api::rest::LabelID;
#[derive(clap::Args, Debug, Default)]
pub struct LabelSelect {
#[arg(short = 'L', long = "label")]
label_names: Option<Vec<String>>,
#[arg(long = "label_id")]
label_ids: Option<Vec<LabelID>>,
}
#[derive(PartialEq, Eq)]
pub enum Selection {
AllowEmpty,
MustChoose,
}
impl LabelSelect {
pub fn is_empty(&self) -> bool {
self.label_ids.is_none() && self.label_names.is_none()
}
pub fn labels(&self, labels: &[Label], selection: Selection) -> Result<Vec<Label>> {
let label_ids = self.label_ids.clone().unwrap_or_default();
let mut all_labels = labels
.iter()
.map(|l| (l.id.clone(), l.to_owned()))
.collect::<HashMap<_, _>>();
let label_list = all_labels
.values()
.map(ToOwned::to_owned)
.collect::<Vec<_>>();
let mut found_labels = label_ids
.into_iter()
.map(|l| {
all_labels
.get(&l)
.ok_or_else(|| eyre!("could not find label with id {}", l))
})
.collect::<Result<Vec<_>>>()?
.iter()
.map(|&l| l.to_owned())
.collect::<Vec<_>>();
if self.label_names.is_none() {
if found_labels.is_empty() && selection == Selection::MustChoose {
return Ok(vec![
all_labels
.remove(
&label_list[interactive::select(
"Select label",
&label_list.iter().map(FullLabel).collect::<Vec<_>>(),
)?
.ok_or_else(|| eyre!("no labels selected"))?]
.id,
)
.unwrap(),
]);
}
return Ok(found_labels);
}
found_labels.extend(
self.label_names
.as_ref()
.unwrap()
.iter()
.map(|label| {
interactive::fuzz_select(&label_list, label)
.map(|label| all_labels.remove(&label.id).unwrap())
})
.collect::<Result<Vec<_>>>()?,
);
Ok(found_labels)
}
}