1use aurora_core::{AuroraResult, Pipeline, Value};
2use std::sync::Mutex;
3use std::time::{Duration, Instant};
4
5#[derive(Clone)]
6struct TimerEntry {
7 name: String,
8 total_secs: u64,
9 started: Instant,
10}
11
12static TIMERS: Mutex<Option<Vec<TimerEntry>>> = Mutex::new(None);
13
14fn get_timers() -> Vec<TimerEntry> {
15 let guard = TIMERS.lock().unwrap_or_else(|e| e.into_inner());
16 guard.clone().unwrap_or_default()
17}
18
19fn set_timers(timers: Vec<TimerEntry>) {
20 let mut guard = TIMERS.lock().unwrap_or_else(|e| e.into_inner());
21 *guard = Some(timers);
22}
23
24pub fn timer_start(seconds: u64, name: Option<&str>) -> AuroraResult<Pipeline> {
25 let name = name.unwrap_or("timer").to_string();
26 let entry = TimerEntry {
27 name: name.clone(),
28 total_secs: seconds,
29 started: Instant::now(),
30 };
31
32 let mut timers = get_timers();
33 timers.push(entry);
34 set_timers(timers);
35
36 let name_clone = name.clone();
37 std::thread::spawn(move || {
38 std::thread::sleep(Duration::from_secs(seconds));
39 let _ = std::io::Write::write_all(
40 &mut std::io::stdout(),
41 format!("\x07\x1b[1;32m=== Timer '{}' finished! ===\x1b[0m\n", name_clone).as_bytes(),
42 );
43 });
44
45 Ok(Pipeline::table(
46 vec!["name".into(), "seconds".into(), "status".into()],
47 vec![vec![
48 Value::String(name),
49 Value::Int(seconds as i64),
50 Value::String("started".into()),
51 ]],
52 ))
53}
54
55pub fn timer_stop() -> AuroraResult<Pipeline> {
56 let timers = get_timers();
57 let count = timers.len();
58 set_timers(Vec::new());
59
60 Ok(Pipeline::table(
61 vec!["action".into(), "stopped".into()],
62 vec![vec![
63 Value::String("stop".into()),
64 Value::Int(count as i64),
65 ]],
66 ))
67}
68
69pub fn timer_status() -> AuroraResult<Pipeline> {
70 let timers = get_timers();
71 let mut rows: Vec<Vec<Value>> = Vec::new();
72
73 for timer in &timers {
74 let elapsed = timer.started.elapsed().as_secs();
75 let remaining = if elapsed >= timer.total_secs {
76 0
77 } else {
78 timer.total_secs - elapsed
79 };
80
81 rows.push(vec![
82 Value::String(timer.name.clone()),
83 Value::Int(remaining as i64),
84 Value::Int(timer.total_secs as i64),
85 ]);
86 }
87
88 Ok(Pipeline::table(
89 vec!["name".into(), "remaining".into(), "total".into()],
90 rows,
91 ))
92}