use std::collections::HashMap;

use godot::classes::{ENetMultiplayerPeer, ICharacterBody3D, INode, Node};
use godot::meta::ParamType;
use godot::obj::{NewGd, WithBaseField};
use godot::prelude::*;

use crate::globals;

use super::player_data::PlayerData;

#[derive(GodotClass)]
#[class(base=Node)]
struct GameServer {
    base: Base<Node>,
    #[export]
    port: i32,
    #[export]
    player_limit: i32,
    #[export]
    current_map: GString,
    #[export]
    current_player_data: Gd<PlayerData>,
    #[export]
    pub(crate) players: Dictionary
}

#[godot_api]
impl INode for GameServer {
    fn init(base: Base<Node>) -> Self {
        let players = Dictionary::new();
        Self {
            base,
            players,
            port: 27015,
            player_limit: 10,
            current_map: "lowpoly_tdm_2".into(),
            current_player_data: PlayerData::new_gd(),
        }
    }

    fn ready(&mut self) {
        if let Some(multiplayer) = self.base().get_multiplayer() {
            let on_connected = multiplayer.callable("peer_connected");
            self.base_mut().connect("on_player_connected", &on_connected);
        }
    }
}

#[godot_api]
impl GameServer {
    // Signals
    #[func]
    fn on_player_connected(&mut self, id: i32) {
        godot_print!("test");
    }
    // Main methods
    #[func]
    fn create_server(&mut self, server_only: bool) {
        let mut peer = ENetMultiplayerPeer::new_gd();
        let server = peer.create_server_ex(self.port)
            .max_clients(self.player_limit)
            .done();
        
        if let Some(mut multiplayer) = self.base().get_multiplayer() {
            let id = multiplayer.get_unique_id();
            multiplayer.set_multiplayer_peer(&peer);
            let player = PlayerData::new_gd();
            self.players.set(id, player);
        }
    }
    #[func]
    fn join_server(&mut self, ip: GString, port: i32) {
        let mut peer = ENetMultiplayerPeer::new_gd();
        peer.create_client(&ip, port);
        if let Some(mut multiplayer) = self.base().get_multiplayer() {
            multiplayer.set_multiplayer_peer(&peer);
        }
    }
}
