pomo_cli/
controller.rs

1use crate::timer::{Timer, TimerEvent, TimerType};
2use flume;
3use std::collections::HashMap;
4use std::sync::Arc;
5use std::sync::Mutex;
6use std::time::Duration;
7use tokio::task;
8
9#[derive(Clone)]
10pub struct Config {
11    pub work_duration: Duration,
12    pub break_duration: Duration,
13    pub long_break_duration: Duration,
14    pub long_break_interval: u64,
15    pub auto: bool,
16}
17
18pub struct Controller {
19    timer: Arc<Mutex<Timer>>,
20    tx: flume::Sender<String>,
21    rx: flume::Receiver<String>,
22    config: Config,
23    event_handlers: HashMap<TimerEvent, Vec<Arc<dyn Fn(&Timer) + Send + Sync>>>,
24    num_finished_timers: u64,
25}
26
27impl Controller {
28    pub fn new(config: Config) -> Arc<Mutex<Controller>> {
29        let (tx, rx) = flume::unbounded();
30
31        let Config { work_duration, .. } = config;
32
33        let timer = Controller::create_timer(tx.clone(), TimerType::Work, work_duration);
34
35        Arc::new(Mutex::new(Controller {
36            config,
37            timer,
38            tx,
39            rx,
40            event_handlers: HashMap::new(),
41            num_finished_timers: 0,
42        }))
43    }
44
45    fn create_timer(
46        tx: flume::Sender<String>,
47        timer_type: TimerType,
48        duration: Duration,
49    ) -> Arc<Mutex<Timer>> {
50        // create a new timer
51        let timer = Timer::new(timer_type, &duration.clone());
52
53        let mut timer_guard = timer.lock().expect("Failed to lock timer");
54
55        // add Finish event handler (only used for auto mode to start next timer)
56        timer_guard.on(
57            TimerEvent::Finish,
58            Arc::new(move |_: &Timer| {
59                tx.send("timer_finished".to_string())
60                    .expect("Failed to send timer finished message");
61            }),
62        );
63
64        drop(timer_guard);
65
66        timer
67    }
68
69    fn attach_timer_handlers(&self) {
70        let mut timer = self.timer.lock().expect("Failed to lock timer");
71
72        // attach saved event handlers to timer
73        for (event, handlers) in &self.event_handlers {
74            for handler in handlers {
75                timer.on(*event, handler.clone());
76            }
77        }
78    }
79
80    pub fn start(controller: &Arc<Mutex<Self>>) {
81        let controller = Arc::clone(controller);
82
83        let mut controller_guard_1 = controller.lock().expect("Failed to lock controller");
84        let rx = controller_guard_1.rx.clone();
85
86        controller_guard_1.start_current_timer();
87        drop(controller_guard_1);
88
89        task::spawn(async move {
90            loop {
91                let msg = rx
92                    .recv_async()
93                    .await
94                    .expect("Failed to listen to socket messages");
95
96                let mut controller_guard_2 = controller.lock().expect("Failed to lock controller");
97
98                match msg.as_str() {
99                    "timer_finished" => {
100                        controller_guard_2.on_timer_finished();
101                    }
102                    "skip" => {
103                        controller_guard_2.start_next_timer();
104                    }
105                    _ => {}
106                }
107
108                drop(controller_guard_2);
109            }
110        });
111    }
112
113    // TODO: These methods look like they can be refactored into a single method
114    pub fn next(controller: &Arc<Mutex<Self>>) {
115        let mut controller = controller.lock().expect("Failed to lock controller");
116        controller.start_next_timer();
117    }
118
119    pub fn stop(controller: &Arc<Mutex<Self>>) {
120        let mut controller = controller.lock().expect("Failed to lock controller");
121        controller.stop_current_timer();
122    }
123
124    pub fn pause(controller: &Arc<Mutex<Self>>) {
125        let mut controller = controller.lock().expect("Failed to lock controller");
126        controller.pause_current_timer();
127    }
128
129    fn start_current_timer(&mut self) {
130        Timer::start(&self.timer);
131    }
132
133    fn stop_current_timer(&mut self) {
134        let mut timer = self.timer.lock().expect("Failed to lock timer");
135        timer.stop();
136    }
137
138    fn pause_current_timer(&mut self) {
139        let mut timer = self.timer.lock().expect("Failed to lock timer");
140        timer.pause();
141    }
142
143    fn start_next_timer(&mut self) {
144        self.num_finished_timers += 1;
145
146        self.stop_current_timer();
147
148        let current_timer = self.timer.lock().expect("Failed to lock timer");
149
150        let new_timer = match current_timer.timer_type() {
151            TimerType::Work => {
152                let mut duration = self.config.break_duration.clone();
153
154                let num_finished_break_timers = self.num_finished_timers / 2;
155
156                if num_finished_break_timers != 0
157                    && num_finished_break_timers % (self.config.long_break_interval - 1) == 0
158                {
159                    duration = self.config.long_break_duration.clone();
160                }
161
162                Controller::create_timer(self.tx.clone(), TimerType::Break, duration)
163            }
164            TimerType::Break => Controller::create_timer(
165                self.tx.clone(),
166                TimerType::Work,
167                self.config.work_duration.clone(),
168            ),
169        };
170
171        drop(current_timer);
172
173        self.timer = new_timer;
174
175        self.attach_timer_handlers();
176
177        self.start_current_timer();
178    }
179
180    fn on_timer_finished(&mut self) {
181        // if Controller is in auto mode, start next timer
182        if self.config.auto {
183            self.start_next_timer();
184            return;
185        }
186    }
187
188    pub fn get_current_timer(controller: &Arc<Mutex<Self>>) -> Arc<Mutex<Timer>> {
189        let controller = Arc::clone(controller);
190
191        let controller = controller.lock().expect("Failed to lock controller");
192        let timer = Arc::clone(&controller.timer);
193        // drop(controller);
194        timer
195    }
196
197    pub fn on(
198        controller: &Arc<Mutex<Self>>,
199        event: TimerEvent,
200        callback: Arc<dyn Fn(&Timer) + Send + Sync>,
201    ) {
202        let mut controller = controller.lock().expect("Failed to lock controller");
203
204        // save the handler for future timers
205        controller
206            .event_handlers
207            .entry(event)
208            .or_default()
209            .push(callback.clone());
210
211        // attach event listener to current timer
212        let mut timer = controller.timer.lock().expect("Failed to lock timer");
213
214        // attach the listener to the current timer
215        timer.on(event, callback);
216    }
217}