use aurora_core::{AuroraResult, Pipeline, Value};
use std::sync::Mutex;
use std::time::{Duration, Instant};
#[derive(Clone)]
struct TimerEntry {
name: String,
total_secs: u64,
started: Instant,
}
static TIMERS: Mutex<Option<Vec<TimerEntry>>> = Mutex::new(None);
fn get_timers() -> Vec<TimerEntry> {
let guard = TIMERS.lock().unwrap_or_else(|e| e.into_inner());
guard.clone().unwrap_or_default()
}
fn set_timers(timers: Vec<TimerEntry>) {
let mut guard = TIMERS.lock().unwrap_or_else(|e| e.into_inner());
*guard = Some(timers);
}
pub fn timer_start(seconds: u64, name: Option<&str>) -> AuroraResult<Pipeline> {
let name = name.unwrap_or("timer").to_string();
let entry = TimerEntry {
name: name.clone(),
total_secs: seconds,
started: Instant::now(),
};
let mut timers = get_timers();
timers.push(entry);
set_timers(timers);
let name_clone = name.clone();
std::thread::spawn(move || {
std::thread::sleep(Duration::from_secs(seconds));
let _ = std::io::Write::write_all(
&mut std::io::stdout(),
format!("\x07\x1b[1;32m=== Timer '{}' finished! ===\x1b[0m\n", name_clone).as_bytes(),
);
});
Ok(Pipeline::table(
vec!["name".into(), "seconds".into(), "status".into()],
vec![vec![
Value::String(name),
Value::Int(seconds as i64),
Value::String("started".into()),
]],
))
}
pub fn timer_stop() -> AuroraResult<Pipeline> {
let timers = get_timers();
let count = timers.len();
set_timers(Vec::new());
Ok(Pipeline::table(
vec!["action".into(), "stopped".into()],
vec![vec![
Value::String("stop".into()),
Value::Int(count as i64),
]],
))
}
pub fn timer_status() -> AuroraResult<Pipeline> {
let timers = get_timers();
let mut rows: Vec<Vec<Value>> = Vec::new();
for timer in &timers {
let elapsed = timer.started.elapsed().as_secs();
let remaining = if elapsed >= timer.total_secs {
0
} else {
timer.total_secs - elapsed
};
rows.push(vec![
Value::String(timer.name.clone()),
Value::Int(remaining as i64),
Value::Int(timer.total_secs as i64),
]);
}
Ok(Pipeline::table(
vec!["name".into(), "remaining".into(), "total".into()],
rows,
))
}