use super::Command;
use crate::err::Error;
use async_trait::async_trait;
use clap::{Arg, ArgMatches, Command as ClapCommand};
pub struct PickCommand;
static QUERY_HELP: &str = r#"Fliter questions by conditions:
Uppercase means negative
e = easy E = m+h
m = medium M = e+h
h = hard H = e+m
d = done D = not done
l = locked L = not locked
s = starred S = not starred"#;
#[async_trait]
impl Command for PickCommand {
fn usage<'a>() -> ClapCommand<'a> {
ClapCommand::new("pick")
.about("Pick a problem")
.visible_alias("p")
.arg(Arg::with_name("id").help("Problem id").takes_value(true))
.arg(
Arg::with_name("plan")
.short('p')
.long("plan")
.takes_value(true)
.help("Invoking python scripts to filter questions"),
)
.arg(
Arg::with_name("query")
.short('q')
.long("query")
.takes_value(true)
.help(QUERY_HELP),
)
.arg(
Arg::with_name("tag")
.short('t')
.long("tag")
.takes_value(true)
.help("Filter questions by tag"),
)
.arg(
Arg::with_name("daily")
.short('d')
.long("daily")
.takes_value(false)
.help("Pick today's daily challenge"),
)
}
async fn handler(m: &ArgMatches) -> Result<(), Error> {
use crate::cache::Cache;
use rand::Rng;
let cache = Cache::new()?;
let mut problems = cache.get_problems()?;
if problems.is_empty() {
cache.download_problems().await?;
Self::handler(m).await?;
return Ok(());
}
#[cfg(feature = "pym")]
{
if m.contains_id("plan") {
let ids = crate::pym::exec(m.value_of("plan").unwrap_or(""))?;
crate::helper::squash(&mut problems, ids)?;
}
}
if m.contains_id("tag") {
let ids = cache
.clone()
.get_tagged_questions(m.value_of("tag").unwrap_or(""))
.await?;
crate::helper::squash(&mut problems, ids)?;
}
if m.contains_id("query") {
let query = m.value_of("query").ok_or(Error::NoneError)?;
crate::helper::filter(&mut problems, query.to_string());
}
let daily_id = if m.contains_id("daily") {
Some(cache.get_daily_problem_id().await?)
} else {
None
};
let fid = m
.value_of("id")
.and_then(|id| id.parse::<i32>().ok())
.or(daily_id)
.unwrap_or_else(|| {
let problem = &problems[rand::thread_rng().gen_range(0..problems.len())];
problem.fid
});
let r = cache.get_question(fid).await;
match r {
Ok(q) => println!("{}", q.desc()),
Err(e) => {
eprintln!("{:?}", e);
if let Error::NetworkError(_) = e {
Self::handler(m).await?;
}
}
}
Ok(())
}
}