use ratatui::layout::Rect;
use tokio::sync::mpsc::UnboundedSender;
use tui_input::Input;
use uuid::Uuid;
use crate::common::{
client::{
channel::SendError,
simple_move::SimpleUserMove,
state::{ClientStateView, RpsState},
},
message::{HashWithData, RpsData, UserState},
};
use super::ClientOptions;
#[derive(Debug)]
pub struct App {
pub running: bool,
pub hide_inputs: bool,
pub input: Input,
pub user_tried_to_change_state_already: bool,
pub submit_error: Option<String>,
pub pop_up: Option<Rect>,
pub client_state: ClientStateView,
pub old_plays: Vec<Box<[(Uuid, HashWithData)]>>,
pub confirm_button: Option<Rect>,
umove_send: UnboundedSender<SimpleUserMove>,
}
impl App {
pub fn new(umove_send: UnboundedSender<SimpleUserMove>, opts: &ClientOptions) -> Self {
Self {
running: true,
user_tried_to_change_state_already: false,
hide_inputs: opts.hide_inputs,
confirm_button: None,
submit_error: None,
pop_up: None,
input: Default::default(),
client_state: Default::default(),
old_plays: vec![],
umove_send,
}
}
pub fn tick(&mut self) {}
pub fn quit(&mut self) {
self.running = false;
}
pub fn do_move(&self, umove: SimpleUserMove) -> Result<(), SendError> {
Ok(self.umove_send.send(umove)?)
}
pub fn text_input_allowed(&self) -> bool {
match self.client_state.state {
RpsState::BeforeRoom => true,
RpsState::InRoom => true,
RpsState::Played => false,
RpsState::Confirmed => false,
}
}
pub fn close_err_pop_up(&mut self) {
self.pop_up = None;
self.submit_error = None;
}
pub fn input_max_length(&self) -> u16 {
const MAX_U64_LEN: u16 = u64::MAX.ilog10() as u16 + 1;
const MAX_DATA_LEN: u16 = RpsData::LEN as u16;
match self.client_state.state {
RpsState::BeforeRoom => MAX_U64_LEN,
RpsState::InRoom => MAX_DATA_LEN,
RpsState::Played => 0,
RpsState::Confirmed => 0,
}
}
pub fn is_waiting_for_others(&self) -> bool {
if let Some(room) = self.client_state.room.as_ref() {
if let Some(round) = room.round.as_ref() {
if !round.users.contains(&self.client_state.user) {
true
} else {
let own_state = self.client_state.state;
for user in &round.users {
if *user == self.client_state.user {
continue;
}
if let Some(state) = self.client_state.cache.get(user) {
let rps_state = match state {
UserState::InRoom => RpsState::InRoom,
UserState::Played(_) => RpsState::Played,
UserState::Confirmed(_) => RpsState::Confirmed,
};
let is_waiting = match own_state {
RpsState::BeforeRoom => false,
RpsState::InRoom => rps_state == RpsState::Confirmed,
RpsState::Played => rps_state == RpsState::InRoom,
RpsState::Confirmed => rps_state == RpsState::Played,
};
if is_waiting {
return true;
}
}
}
false
}
} else {
false
}
} else {
false
}
}
}