use std::fmt::Display;
use std::hash::Hash;
use crate::common::connection::{WriteMessageError, Writer};
use crate::common::message::ServerMessage;
use crate::common::message::{RoomId, RoomState};
use super::types::{Connections, RoomData, Rooms};
pub async fn get_room_state<P: Hash>(rooms: &Rooms<P>, room_id: RoomId) -> Option<RoomState> {
let rooms = rooms.lock().await;
let room: &RoomData<_> = rooms.get(&room_id)?;
let mut users: Box<[_]> = room.users.values().copied().collect();
let round = room.round.clone();
drop(rooms);
users.sort_by_key(|u| u.id);
Some(RoomState {
id: room_id,
users,
round,
})
}
#[derive(thiserror::Error, Debug)]
pub enum SendRoomUpdateError {
#[error("{}", .0)]
WriteMessageError(#[from] WriteMessageError),
#[error("{}", .0)]
Other(String),
}
impl From<String> for SendRoomUpdateError {
fn from(value: String) -> Self {
SendRoomUpdateError::Other(value)
}
}
pub async fn send_room_update<P: Display + std::hash::Hash + Clone + Eq, W: Writer>(
room_id: RoomId,
rooms: &Rooms<P>,
streams: &Connections<P, W>,
) -> Result<(), SendRoomUpdateError> {
let new_state = get_room_state(rooms, room_id)
.await
.ok_or_else(|| format!("No state for {room_id:?}"))?;
if let Some(set) = rooms.lock().await.get(&room_id) {
for (peer, user) in set.users.iter() {
let mut guard = streams.lock().await;
let stream = if let Some(stream) = guard.get_mut(peer) {
stream
} else {
continue;
};
log::info!(
"Calling room_update for {peer} ({}) in room {room_id}",
user.id
);
stream
.write_message(ServerMessage::RoomUpdate {
new_state: new_state.clone(),
})
.await?;
}
}
Ok(())
}