use chrono::NaiveDate;
use regex::Regex;
use serde::Deserialize;
use structopt::{clap::arg_enum, StructOpt};
use std::path::PathBuf;
use crate::{
error::{Error, Result},
tag::Tag,
};
use super::PriceTags;
#[derive(Debug, StructOpt)]
#[structopt(author)]
pub struct Args {
#[structopt(long, global = true)]
pub clear_cache: bool,
#[structopt(long, short, env = "MENSA_CONFIG", name = "PATH", global = true)]
pub config: Option<PathBuf>,
#[cfg_attr(windows, doc = "Not available")]
#[structopt(long, env = "MENSA_ASCII_ONLY", global = true, takes_value = false)]
pub plain: bool,
#[structopt(
long,
global = true,
value_name = "WHEN",
default_value = "Automatic",
possible_values = &ColorWhen::variants(),
case_insensitive = true
)]
pub color: ColorWhen,
#[structopt(long, global = true, takes_value = false)]
pub json: bool,
#[structopt(subcommand)]
pub command: Option<Command>,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, StructOpt)]
pub enum Command {
Canteens(CanteensCommand),
Tags,
Meals(MealsCommand),
}
#[derive(Debug, StructOpt)]
pub struct CanteensCommand {
#[structopt(long, short)]
pub all: bool,
#[structopt(flatten)]
pub geo: GeoCommand,
}
#[derive(Debug, Clone, StructOpt)]
pub enum CloseCommand {
Close(GeoCommand),
}
#[derive(Debug, Clone, StructOpt)]
pub struct GeoCommand {
#[structopt(long)]
pub lat: Option<f32>,
#[structopt(long)]
pub long: Option<f32>,
#[structopt(long, short, default_value = "10")]
pub radius: f32,
}
#[derive(Debug, Clone, StructOpt)]
pub struct MealsCommand {
#[structopt(
long, short,
global = true,
env = "MENSA_DATE",
parse(try_from_str = parse_human_date),
default_value = "today",
global = true
)]
pub date: NaiveDate,
#[structopt(long = "id", global = true, short = "i", env = "MENSA_ID")]
pub canteen_id: Option<usize>,
#[structopt(
long,
short,
global = true,
env = "MENSA_PRICES",
possible_values = &PriceTags::variants(),
case_insensitive = true
)]
pub price: Option<Vec<PriceTags>>,
#[structopt(
long,
global = true,
env = "MENSA_OVERWRITE_FILTER",
takes_value = false
)]
pub overwrite_filter: bool,
#[structopt(long, global = true, env = "MENSA_FILTER_NAME_ADD")]
pub filter_name: Vec<Regex>,
#[structopt(long, global = true, env = "MENSA_FILTER_NAME_SUB")]
pub no_filter_name: Vec<Regex>,
#[structopt(
long,
global = true,
env = "MENSA_FILTER_TAG_ADD",
parse(try_from_str = serde_plain::from_str)
)]
pub filter_tag: Vec<Tag>,
#[structopt(
long,
global = true,
env = "MENSA_FILTER_TAG_SUB",
parse(try_from_str = serde_plain::from_str)
)]
pub no_filter_tag: Vec<Tag>,
#[structopt(long, global = true, env = "MENSA_FILTER_CATEGORY_ADD")]
pub filter_cat: Vec<Regex>,
#[structopt(long, global = true, env = "MENSA_FILTER_CATEGORY_SUB")]
pub no_filter_cat: Vec<Regex>,
#[structopt(long, global = true, env = "MENSA_OVERWRITE_FAVS", takes_value = false)]
pub overwrite_favs: bool,
#[structopt(long, global = true, env = "MENSA_FAVS_NAME_ADD")]
pub favs_name: Vec<Regex>,
#[structopt(long, global = true, env = "MENSA_FAVS_NAME_SUB")]
pub no_favs_name: Vec<Regex>,
#[structopt(
long,
global = true,
env = "MENSA_FAVS_TAG_ADD",
parse(try_from_str = serde_plain::from_str)
)]
pub favs_tag: Vec<Tag>,
#[structopt(
long,
global = true,
env = "MENSA_FAVS_TAG_SUB",
parse(try_from_str = serde_plain::from_str)
)]
pub no_favs_tag: Vec<Tag>,
#[structopt(long, global = true, env = "MENSA_FAVS_CATEGORY_ADD")]
pub favs_cat: Vec<Regex>,
#[structopt(long, global = true, env = "MENSA_FAVS_CATEGORY_SUB")]
pub no_favs_cat: Vec<Regex>,
#[structopt(subcommand)]
pub close: Option<CloseCommand>,
}
arg_enum! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
pub enum ColorWhen {
Always,
Automatic,
Never,
}
}
pub fn parse_human_date(inp: &str) -> Result<NaiveDate> {
date_time_parser::DateParser::parse(inp).ok_or(Error::InvalidDateInArgs)
}
impl Default for Command {
fn default() -> Self {
Self::Meals(Default::default())
}
}
impl Default for MealsCommand {
fn default() -> Self {
MealsCommand {
date: parse_human_date("today").unwrap(),
canteen_id: None,
price: None,
overwrite_filter: false,
filter_name: vec![],
no_filter_name: vec![],
filter_tag: vec![],
no_filter_tag: vec![],
filter_cat: vec![],
no_filter_cat: vec![],
overwrite_favs: false,
favs_name: vec![],
no_favs_name: vec![],
favs_tag: vec![],
no_favs_tag: vec![],
favs_cat: vec![],
no_favs_cat: vec![],
close: None,
}
}
}