1use std::collections::HashMap;
2use std::fmt;
3use std::sync::Arc;
4use std::sync::Mutex;
5use tokio::task;
6use tokio::time::{Duration, Instant};
7
8#[derive(Copy, Clone)]
9pub enum TimerType {
10 Work,
11 Break,
12}
13
14impl fmt::Display for TimerType {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 let string = match self {
17 TimerType::Work => "work",
18 TimerType::Break => "break",
19 };
20
21 write!(f, "{}", string)
22 }
23}
24
25#[derive(Copy, Clone, Eq, PartialEq, Hash)]
26pub enum TimerEvent {
27 Finish,
28 Start,
29 Pause,
30 Stop,
31}
32
33#[derive(Copy, Clone)]
34pub enum TimerState {
35 Running,
36 Paused,
37 Stopped,
38}
39
40pub struct Timer {
41 remaining: Duration,
42 handle: Option<tokio::task::JoinHandle<()>>,
43 state: TimerState,
44 last_started_at: Option<Instant>,
45 timer_type: TimerType,
46 event_handlers: HashMap<TimerEvent, Vec<Arc<dyn Fn(&Timer) + Send + Sync>>>,
47}
48
49impl Timer {
50 pub fn new(timer_type: TimerType, duration: &Duration) -> Arc<Mutex<Timer>> {
51 Arc::new(Mutex::new(Timer {
52 event_handlers: HashMap::new(),
53 handle: None,
54 last_started_at: None,
55 remaining: duration.clone(),
56 state: TimerState::Stopped,
57 timer_type,
58 }))
59 }
60
61 pub fn start(timer: &Arc<Mutex<Timer>>) {
62 let timer = Arc::clone(timer);
63
64 let mut timer_guard = timer.lock().expect("Failed to lock timer");
65
66 if let TimerState::Running = timer_guard.state {
67 return;
68 }
69
70 let duration = timer_guard.time_left();
71
72 let timer2 = Arc::clone(&timer);
73
74 let handle = task::spawn(async move {
75 tokio::time::sleep(duration).await;
76
77 let mut timer_guard = timer2.lock().expect("Failed to lock timer");
78 timer_guard.finished();
79 });
80
81 timer_guard.handle = Some(handle);
82 timer_guard.last_started_at = Some(Instant::now());
83 timer_guard.state = TimerState::Running;
84
85 timer_guard.event(TimerEvent::Start);
86 }
87
88 pub fn stop(&mut self) {
89 self.state = TimerState::Stopped;
90
91 self.abort_current_task();
93
94 self.event(TimerEvent::Stop);
95 }
96
97 pub fn pause(&mut self) {
98 if let TimerState::Running = self.state {
100 self.remaining = self.time_left();
101
102 self.abort_current_task();
104
105 self.state = TimerState::Paused;
106
107 self.event(TimerEvent::Pause);
108 }
109 }
110
111 pub fn time_left(&self) -> Duration {
112 let elapsed = match &self.state {
113 TimerState::Running => match self.last_started_at {
114 Some(last_started_at) => last_started_at.elapsed(),
115 None => Duration::ZERO,
116 },
117 _ => Duration::ZERO,
118 };
119
120 if elapsed <= self.remaining {
121 self.remaining - elapsed
122 } else {
123 Duration::ZERO
124 }
125 }
126
127 pub fn on(&mut self, event: TimerEvent, callback: Arc<dyn Fn(&Timer) + Send + Sync>) {
128 self.event_handlers
129 .entry(event)
130 .or_default()
131 .push(callback.clone());
132 }
133
134 pub fn timer_type(&self) -> TimerType {
135 self.timer_type.clone()
136 }
137
138 pub fn clone(&self) -> Timer {
139 Timer {
140 handle: None,
141 last_started_at: self.last_started_at.clone(),
142 remaining: self.remaining.clone(),
143 state: self.state.clone(),
144 timer_type: self.timer_type.clone(),
145 event_handlers: HashMap::new(),
146 }
147 }
148
149 fn abort_current_task(&self) {
150 if let Some(handle) = &self.handle {
151 handle.abort();
152 }
153 }
154
155 fn finished(&mut self) {
156 self.remaining = Duration::ZERO;
157 self.state = TimerState::Stopped;
158
159 self.event(TimerEvent::Finish);
160 }
161
162 fn event(&self, event: TimerEvent) {
163 if let Some(handlers) = self.event_handlers.get(&event) {
164 for callback in handlers {
165 callback(&*self);
166 }
167 }
168 }
169}
170
171