use std::collections::HashMap; use futures::future::join_all; use gamenight_api_client_rs::{apis::default_api::{game_get, owned_games_get, participants_get, user_get, GameGetError}, models::{self, GameId, GamenightId, UserId}}; use inquire::Select; use uuid::Uuid; use crate::{domain::{game::Game, gamenight::Gamenight, owned_games::OwnedGames, participants::Participants, user::User}, flows::{exit::Exit, join::Join, leave::Leave}}; use super::*; #[derive(Clone)] pub struct ViewGamenight { gamenight: Gamenight } impl ViewGamenight { pub fn new(gamenight: Gamenight) -> Self { Self { gamenight } } } impl From for FlowError { fn from(value: jsonwebtoken::errors::Error) -> Self { Self { error: value.to_string() } } } #[async_trait] impl<'a> Flow<'a> for ViewGamenight { async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> { let participants = participants_get(&state.api_configuration, Some(GamenightId{gamenight_id: self.gamenight.id.to_string()})).await?; let mut users = vec![]; for participant in participants.participants.iter() { let user = user_get(&state.api_configuration, Some(UserId{user_id: participant.clone()})).await?; users.push(User { id: Uuid::parse_str(&user.id)?, username: user.username }); } let mut user_games: HashMap> = HashMap::new(); for user in &users { let request = UserId{ user_id: user.id.to_string() }; let games: Vec = join_all(owned_games_get(&state.api_configuration, Some(request)).await? .iter().map(async |game_id| -> Result> { let request = GameId{ game_id: game_id.clone() }; game_get(&state.api_configuration, Some(request)).await })).await.into_iter().collect::, Error>>()?.into_iter().map(Into::into).collect(); user_games.insert(user.username.clone(), games); } println!("{}\nwho: {}\nGames:\n{}", self.gamenight, Participants(&users), OwnedGames(&user_games)); let my_uid = state.get_user_id()?; let join_or_leave: Box + Send> = if users.iter().map(|x| {x.id}).any(|x| x == my_uid) { Box::new(Leave::new(self.gamenight.id)) } else { Box::new(Join::new(self.gamenight.id)) }; let options: Vec + Send>> = vec![ join_or_leave, Box::new(Exit::new()) ]; let choice = Select::new("What do you want to do:", options) .prompt_skippable()?; self.continue_choice(state, &choice).await } } impl Display for ViewGamenight { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} {}", self.gamenight.name, self.gamenight.start_time.format("%d-%m-%Y %H:%M")) } }