1pub mod output;
2
3mod builder;
4mod state;
5
6pub use builder::TimerBuilder;
7pub use output::Output;
8pub use state::TimerState;
9
10use std::thread::sleep;
11use std::time::{Duration, Instant, SystemTime};
12
13use crate::error::{ClimerError, ClimerResult};
14use crate::settings::timer::*;
15use crate::time::Time;
16
17#[derive(Clone)]
18struct TimerLastUpdate {
19 pub time: SystemTime,
20 pub instant: Instant,
21}
22
23impl TimerLastUpdate {
24 pub fn now() -> Self {
25 Self {
26 time: SystemTime::now(),
27 instant: Instant::now(),
28 }
29 }
30}
31
32#[derive(Clone)]
33pub struct Timer {
34 pub state: TimerState,
35 target_time: Option<Time>,
36 time: Time,
37 start_time: Option<Time>,
38 continue_after_finish: bool,
39 output: Option<Output>,
40 update_delay_ms: u64,
41 last_update: Option<TimerLastUpdate>,
42}
43
44impl Timer {
45 pub fn builder() -> TimerBuilder {
47 TimerBuilder::default()
48 }
49
50 pub fn new(target_time: Option<Time>, output: Option<Output>) -> Self {
56 Self {
57 state: TimerState::Stopped,
58 target_time,
59 time: Time::zero(),
60 start_time: None,
61 continue_after_finish: false,
62 output,
63 update_delay_ms: 100, last_update: None,
65 }
66 }
67
68 pub fn set_target_time(&mut self, target_time: Time) {
70 self.target_time = Some(target_time);
71 }
72
73 pub fn set_continue_after_finish(&mut self, continue_after_finish: bool) {
74 self.continue_after_finish = continue_after_finish;
75 }
76
77 pub fn clear_target_time(&mut self) {
81 self.target_time = None;
82 }
83
84 pub fn set_start_time(&mut self, start_time: Time) {
87 self.start_time = Some(start_time);
88 }
89
90 pub fn clear_start_time(&mut self) {
92 self.start_time = None;
93 }
94
95 pub fn run(&mut self) -> ClimerResult {
100 self.start()?;
101 while self.state.is_running() {
102 self.update()?;
103 sleep(Duration::from_millis(self.update_delay_ms))
104 }
105 Ok(())
106 }
107
108 pub fn start(&mut self) -> ClimerResult {
113 self.time = self
114 .start_time
115 .as_ref()
116 .map(Clone::clone)
117 .unwrap_or_else(Time::zero);
118 self.state = TimerState::Running;
119 self.last_update = Some(TimerLastUpdate::now());
120
121 Ok(())
122 }
123
124 pub fn stop(&mut self) -> ClimerResult {
126 self.state = TimerState::Stopped;
127 self.last_update = None;
128 Ok(())
129 }
130
131 pub fn pause(&mut self) -> ClimerResult {
133 match &self.state {
134 TimerState::Running => {
135 self.update()?;
136 self.last_update = None;
137 self.state = TimerState::Paused;
138 Ok(())
139 }
140 _ => Err(ClimerError::TimerNotRunning),
141 }
142 }
143
144 pub fn resume(&mut self) -> ClimerResult {
146 match &self.state {
147 TimerState::Paused => {
148 self.last_update = Some(TimerLastUpdate::now());
149 self.update()?;
150 self.state = TimerState::Running;
151 Ok(())
152 }
153 _ => Err(ClimerError::TimerAlreadyRunning),
154 }
155 }
156
157 pub fn update(&mut self) -> ClimerResult {
161 match &self.state {
162 TimerState::Running => {
163 let now = TimerLastUpdate::now();
164 self.print_output()?;
165
166 let last_update = self
167 .last_update
168 .take()
169 .unwrap_or_else(TimerLastUpdate::now);
170
171 let duration =
172 now.time.duration_since(last_update.time).unwrap_or_else(
173 |_| now.instant.duration_since(last_update.instant),
174 );
175
176 let time_since = Time::from(duration);
177 self.time += time_since;
178
179 if self.target_time.is_some() {
180 self.check_finished()?;
181 }
182
183 self.last_update = Some(now);
184 Ok(())
185 }
186 _ => Ok(()),
187 }
188 }
189
190 pub fn print_output(&mut self) -> ClimerResult {
193 let time_output = self.time_output();
194 if let Some(output) = &mut self.output {
195 output.update(format!("{}", time_output))
196 } else {
197 Ok(())
198 }
199 }
200
201 pub fn time_output(&self) -> Time {
206 if let Some(target_time) = self.target_time {
207 if target_time < self.time {
208 return Time::zero();
209 };
210 target_time - self.time
211 } else {
212 self.time
213 }
214 }
215
216 fn check_finished(&mut self) -> ClimerResult {
219 if !self.state.is_running() {
220 return Err(ClimerError::TimerNotRunning);
221 }
222
223 if let Some(target_time) = self.target_time {
224 if self.time >= target_time {
225 if self.continue_after_finish {
226 self.last_update = Some(TimerLastUpdate::now());
227 self.target_time = None;
228 self.time = self.time - target_time;
229 if let Some(output) = &mut self.output {
230 output.set_prefix(Some("-".to_string()));
231 }
232 } else {
233 if let Some(output) = &mut self.output {
234 output.print(FINISH_TEXT)?;
235 }
236 self.finish_without_update()?;
237 }
238 }
239 Ok(())
240 } else {
241 Err(ClimerError::TimerCannotFinish)
242 }
243 }
244
245 pub fn finish(&mut self) -> ClimerResult {
247 self.update()?; self.finish_without_update()
249 }
250
251 fn finish_without_update(&mut self) -> ClimerResult {
255 self.stop()?;
256 self.state = TimerState::Finished;
257 Ok(())
258 }
259}
260
261impl Default for Timer {
262 fn default() -> Self {
263 Self::new(None, None)
264 }
265}