use std::error::Error;

use dashmap::DashMap;
use paste::paste;

use common::{
    base::NetService,
    impl_net_service,
    net::{tools::Packet, AServer, NetError, ServiceType},
    rpc_handlers, services,
};

use crate::{config::GameserverConfig, gameserver_service, handler::login_handler};

use super::GateserverSession;

pub struct NetworkMgr {
    server: AServer,
    gateserver_sessions: DashMap<u32, GateserverSession>,
}

impl NetworkMgr {
    pub async fn new(config: &GameserverConfig) -> Result<Self, NetError> {
        let inner_ip = config
            .applications
            .get(&ServiceType::Gameserver)
            .unwrap()
            .iter()
            .find(|a| a.app_id == config.app_id)
            .unwrap()
            .inner_ip
            .clone();

        Ok(Self {
            server: AServer::bind(inner_ip).await?,
            gateserver_sessions: DashMap::new(),
        })
    }

    pub async fn run(&self) {
        loop {
            let Ok(mut packets) = self.server.recv().await else {
                continue;
            };

            while let Some(packet) = packets.pop_front() {
                if let Err(err) = self.on_recv_to_svc(packet).await {
                    tracing::warn!("on_recv fail: {err}");
                }
            }
        }
    }

    rpc_handlers! {
        PlayerLoginRsp;
    }

    services! {
        Gateserver;
    }

    pub async fn on_player_login_rsp(&self, packet: Packet) -> Result<(), Box<dyn Error>> {
        login_handler::on_player_login_rsp(packet).await;

        Ok(())
    }

    pub async fn default_packet_process_func(&self, _: Packet) -> Result<(), Box<dyn Error>> {
        Ok(())
    }
}

impl_net_service!(Gameserver);
