132 lines
2.8 KiB
Rust

use std::{fmt::Display, num::ParseIntError};
use async_trait::async_trait;
use chrono::ParseError;
use gamenight_api_client_rs::apis::{configuration::Configuration, Error};
use inquire::InquireError;
use dyn_clone::DynClone;
pub use clear_screen;
use crate::domain::config::{Config, ConfigError};
pub mod main;
mod login;
mod gamenight_menu;
mod exit;
mod list_gamenights;
mod add_gamenight;
mod view_gamenight;
mod join;
mod leave;
mod connect;
mod settings;
pub struct GamenightState {
api_configuration: Configuration,
gamenight_configuration: Config,
}
impl GamenightState {
pub fn new() -> Self{
Self {
api_configuration: Configuration::new(),
gamenight_configuration: Config::new()
}
}
}
impl Default for GamenightState {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug)]
pub struct FlowError {
pub error: String
}
impl From<InquireError> for FlowError {
fn from(value: InquireError) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<ParseError> for FlowError {
fn from(value: ParseError) -> Self {
Self {
error: value.to_string()
}
}
}
impl<T> From<Error<T>> for FlowError {
fn from(value: Error<T>) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<uuid::Error> for FlowError {
fn from(value: uuid::Error) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<ConfigError> for FlowError {
fn from(value: ConfigError) -> Self {
Self {
error: value.0
}
}
}
impl From<ParseIntError> for FlowError {
fn from(value: ParseIntError) -> Self {
Self {
error: value.to_string()
}
}
}
#[derive(PartialEq)]
pub enum FlowOutcome {
Successful,
Bool(bool),
String(String),
Abort
}
type FlowResult<'a> = Result<(FlowOutcome, &'a mut GamenightState), FlowError>;
dyn_clone::clone_trait_object!(for<'a> Flow<'a>);
#[async_trait]
pub trait Flow<'a>: Sync + DynClone + Send + Display {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a>;
}
async fn handle_choice<'a>(choice: &Box<dyn Flow<'a> + Send>, flow: &dyn Flow<'a>, state: &'a mut GamenightState) -> FlowResult<'a> {
let (outcome, new_state) = choice.run(state).await?;
if outcome == FlowOutcome::Abort {
Ok((FlowOutcome::Successful, new_state))
}
else {
flow.run(new_state).await
}
}
async fn handle_choice_option<'a>(choice: &Option<Box<dyn Flow<'a> + Send>>, flow: &dyn Flow<'a>, state: &'a mut GamenightState) -> FlowResult<'a> {
if let Some(choice) = choice {
handle_choice(choice, flow, state).await
}
else {
Ok((FlowOutcome::Abort, state))
}
}