use std::{sync::mpsc, time::Duration};
use crossterm::event::{self, Event as CrosstermEvent, KeyEvent, MouseEvent};
#[derive(Debug)]
pub enum Event<T> {
Key(KeyEvent),
Mouse(MouseEvent),
Tick,
Sim(SimMessage<T>),
Resize,
}
#[derive(Debug, thiserror::Error)]
pub enum SimError {
#[error("simulation panicked")]
Panic,
#[error("comparison failed: {source}")]
ComparisonFailed {
#[source]
source: rs_poker::arena::comparison::ComparisonError,
},
#[error("too many consecutive failures ({consecutive_failures})")]
TooManyFailures { consecutive_failures: usize },
}
#[derive(Debug)]
pub enum SimMessage<T> {
GameResult(T),
Completed,
Error(SimError),
}
pub struct EventHandler<T> {
rx: mpsc::Receiver<SimMessage<T>>,
tick_rate: Duration,
}
impl<T> EventHandler<T> {
pub fn new(rx: mpsc::Receiver<SimMessage<T>>, tick_rate: Duration) -> Self {
Self { rx, tick_rate }
}
pub fn next(&self) -> std::io::Result<Event<T>> {
if let Ok(msg) = self.rx.try_recv() {
return Ok(Event::Sim(msg));
}
if event::poll(self.tick_rate)? {
match event::read()? {
CrosstermEvent::Key(key) => return Ok(Event::Key(key)),
CrosstermEvent::Mouse(mouse) => return Ok(Event::Mouse(mouse)),
CrosstermEvent::Resize(_, _) => return Ok(Event::Resize),
_ => {}
}
}
Ok(Event::Tick)
}
pub fn try_recv_sim(&self) -> Option<SimMessage<T>> {
self.rx.try_recv().ok()
}
}