use std::result::Result as StdResult;
use clap::{
ArgAction,
Subcommand,
ValueEnum
};
use conciliator::{
Buffer,
Claw,
Conciliator,
List
};
use greg::Point;
use greg::real::Scale;
use crate::{
Nunc,
Result
};
use crate::core::{
Log,
Tree,
Measure,
Zone
};
use crate::data::entry::{
Entry,
List as EntryList
};
#[derive(Subcommand)]
pub(crate) enum Cmd {
Recap {
#[clap(short = 'l', long = "last", action = ArgAction::Count)]
offset: u8,
#[clap(value_enum, default_value_t)]
timespan: RecapTimespan
},
Now,
}
#[derive(Clone, Default, ValueEnum)]
pub(crate) enum RecapTimespan {
#[default]
Day,
Week,
Month,
All
}
fn cmd_now(con: &Claw, nunc: &Nunc) -> Result<()> {
let states = nunc
.show()?
.drain(..)
.map(|s| s.make_inline(nunc))
.collect::<StdResult<Vec<_>, _>>()?;
con.print(List::new("Streaks", states.iter()));
let fmt_active = |buf: &mut Buffer, ent: &Entry| {
let activity = nunc.get_activity(ent.activity_id).unwrap();
let (pre, span) = match Point::now() > ent.start {
true => ("for", Point::now() - ent.start),
false => ("in", ent.start - Point::now())
};
buf.push(activity).push(format_args!(": {pre} {span:#}"));
};
List::new("currently running", nunc.get_active_entries()?.iter())
.with_formatter(fmt_active)
.print_to(con);
Ok(())
}
impl Cmd {
pub fn run(self, con: &Claw, nunc: &Nunc) -> Result<()> {
match self {
Self::Now => cmd_now(con, nunc),
Self::Recap{offset, timespan} =>
cmd_recap(con, nunc, offset, timespan),
}
}
}
pub(crate) fn cmd_recap(
con: &Claw,
nunc: &Nunc,
offset: u8,
timespan: RecapTimespan)
-> Result<()>
{
let cal = nunc.load_calendar()?;
let scale = match timespan {
RecapTimespan::Day => Scale::Days,
RecapTimespan::Week => Scale::Weeks,
RecapTimespan::Month => Scale::Months,
RecapTimespan::All => todo!(),
};
let mut frames = cal.frames(scale, Point::now());
let frame = match offset {
0 => frames.next().unwrap(),
n => frames
.rev()
.nth(n as usize - 1)
.unwrap()
};
let entries = nunc.recap(frame)?;
con.print(EntryList::new(nunc, entries.iter())?);
Ok(())
}