pub mod avatar_handler;
pub mod login_handler;
pub mod player_handler;
pub mod player_misc_handler;
pub mod scene_handler;

macro_rules! get_proto {
    ($packet: expr, $proto: ident) => {
        match $packet.get_proto::<::proto::$proto>() {
            Ok(proto) => proto,
            Err(_) => {
                ::tracing::error!(
                    concat!("get_proto ", stringify!($proto), " failed, uid: {}"),
                    $packet.head.user_id
                );
                return Ok(());
            }
        }
    };
}

macro_rules! game_packet_handlers {
    ($($category: ident::$name: ident;)*) => {
        pub fn process_packet(player: &::std::rc::Rc<crate::player::Player>, packet: ::common::net::tools::Packet) -> Result<(), Box<dyn ::std::error::Error>> {
            use ::proto::CmdID;
            ::paste::paste! {
                match packet.cmd_id {
                    $(
                        ::proto::$name::CMD_ID => crate::handler::[<$category:snake>]::[<on_ $name:snake>](player, packet),
                    )*
                    _ => {
                        tracing::warn!("can not find func for cmd_id={}", packet.cmd_id);
                        Ok(())
                    }
                }
            }
        }
    };
}

pub(crate) use get_proto;

game_packet_handlers! {
    PlayerMiscHandler::PingReq;
    PlayerHandler::SetPlayerBornDataReq;
    PlayerHandler::PlayerLogoutReq;
    SceneHandler::EnterSceneReadyReq;
    SceneHandler::SceneInitFinishReq;
    SceneHandler::EnterSceneDoneReq;
    SceneHandler::PostEnterSceneReq;
    AvatarHandler::SetUpAvatarTeamReq;
    AvatarHandler::ChangeAvatarReq;
}
