//! UI event helpers used by peer command and service code.

use std::{net::SocketAddr, sync::Arc};

use tokio::sync::{RwLock, mpsc::UnboundedSender};

use crate::{PeerEvent, peer_db::PeerGameDB};

pub fn send(tx_notify_ui: &UnboundedSender<PeerEvent>, event: PeerEvent) {
    if let Err(err) = tx_notify_ui.send(event) {
        let kind: &'static str = (&err.0).into();
        log::error!("Failed to send {kind} event: channel closed");
    }
}

pub async fn emit_peer_game_list(
    peer_game_db: &Arc<RwLock<PeerGameDB>>,
    tx_notify_ui: &UnboundedSender<PeerEvent>,
) {
    let games = { peer_game_db.read().await.get_all_games() };
    send(tx_notify_ui, PeerEvent::ListGames(games));
}

pub async fn emit_peer_count(
    peer_game_db: &Arc<RwLock<PeerGameDB>>,
    tx_notify_ui: &UnboundedSender<PeerEvent>,
) {
    let peer_count = { peer_game_db.read().await.get_peer_addresses().len() };
    send(tx_notify_ui, PeerEvent::PeerCountUpdated(peer_count));
}

pub async fn emit_peer_discovered(
    peer_game_db: &Arc<RwLock<PeerGameDB>>,
    tx_notify_ui: &UnboundedSender<PeerEvent>,
    peer_addr: SocketAddr,
) {
    send(tx_notify_ui, PeerEvent::PeerDiscovered(peer_addr));
    emit_peer_count(peer_game_db, tx_notify_ui).await;
}

pub async fn emit_peer_lost(
    peer_game_db: &Arc<RwLock<PeerGameDB>>,
    tx_notify_ui: &UnboundedSender<PeerEvent>,
    peer_addr: SocketAddr,
) {
    send(tx_notify_ui, PeerEvent::PeerLost(peer_addr));
    emit_peer_count(peer_game_db, tx_notify_ui).await;
}
