use std::{fmt::Display, rc::Rc};

use data::math_def::Vector3;
use proto::{ProtEntityType, SceneEntityInfo};

use crate::player::Player;

pub trait Entity {
    fn get_entity_type(&self) -> ProtEntityType;
    fn get_group_id(&self) -> u32;
    fn entity_id(&self) -> u32;
    fn set_entity_id(&mut self, id: u32);
    fn position(&self) -> &Vector3;
    fn rotation(&self) -> &Vector3;
    fn set_position(&mut self, pos: Vector3);
    fn set_rotation(&mut self, rot: Vector3);
    fn get_owner_player(&self) -> Option<Rc<Player>>;

    fn is_on_scene(&self) -> bool {
        self.entity_id() != 0
    }

    fn can_enter_region(&self) -> bool {
        false
    }

    fn get_desc(&self) -> String {
        let pos = self.position();
        format!(
            "[entity_id:{},group_id:{},pos:{},{},{}]",
            self.entity_id(),
            self.get_group_id(),
            pos.x,
            pos.y,
            pos.z
        )
    }

    fn get_player_uid(&self) -> u32 {
        match self.get_owner_player() {
            Some(player) => player.uid,
            None => 0,
        }
    }

    fn to_client(&self, _scene_entity_info: &mut SceneEntityInfo) {}
}

impl Display for dyn Entity {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.get_desc())
    }
}
