use data::math_def::Vector3;
use proto::{AbilitySyncStateInfo, Retcode, SceneWeaponInfo};

use crate::{creature::Creature, entity::Entity};

pub struct WeaponGadgetBase {
    pub item_id: u32,
    pub gadget_id: u32,
    level: u32,
    entity_id: u32,
    pos: Vector3,
    rot: Vector3,
}

pub struct AvatarWeaponGadget {
    pub base: WeaponGadgetBase,
    pub weapon_guid: u64,
}

pub enum WeaponGadget {
    Avatar(AvatarWeaponGadget),
}

impl WeaponGadget {
    pub fn new_avatar(item_id: u32, guid: u64) -> Self {
        Self::Avatar(AvatarWeaponGadget {
            base: WeaponGadgetBase {
                item_id,
                gadget_id: 50000000 + item_id, // TODO!
                entity_id: 0,
                level: 1,
                pos: Vector3::default(),
                rot: Vector3::default(),
            },
            weapon_guid: guid,
        })
    }

    pub fn base(&self) -> &WeaponGadgetBase {
        match self {
            Self::Avatar(gadget) => &gadget.base,
        }
    }

    pub fn base_mut(&mut self) -> &mut WeaponGadgetBase {
        match self {
            Self::Avatar(gadget) => &mut gadget.base,
        }
    }

    pub fn init_ability(&mut self) -> Result<(), Retcode> {
        // TODO: self.base_mut().ability_comp ...

        Ok(())
    }

    pub fn to_client(&self) -> SceneWeaponInfo {
        SceneWeaponInfo {
            ability_info: Some(AbilitySyncStateInfo::default()),
            level: self.base().level,
            item_id: self.base().item_id,
            gadget_id: self.base().gadget_id,
            entity_id: self.entity_id(),
            guid: match self {
                Self::Avatar(gadget) => gadget.weapon_guid,
            },
            ..Default::default()
        }
    }
}

impl Creature for WeaponGadget {
    fn set_level(&mut self, level: u32) {
        self.base_mut().level = level;
    }

    fn set_cur_hp_full(&mut self) {}

    fn get_life_state(&self) -> crate::creature::LifeState {
        crate::creature::LifeState::LifeNone
    }

    fn set_life_state(&mut self, _state: crate::creature::LifeState) {}
}

impl Entity for WeaponGadget {
    fn get_entity_type(&self) -> proto::ProtEntityType {
        proto::ProtEntityType::ProtEntityWeapon
    }

    fn get_group_id(&self) -> u32 {
        0
    }

    fn entity_id(&self) -> u32 {
        self.base().entity_id
    }

    fn set_entity_id(&mut self, id: u32) {
        self.base_mut().entity_id = id;
    }

    fn position(&self) -> &Vector3 {
        &self.base().pos
    }

    fn rotation(&self) -> &Vector3 {
        &self.base().rot
    }

    fn get_owner_player(&self) -> Option<std::rc::Rc<crate::player::Player>> {
        None
    }

    fn set_position(&mut self, pos: data::math_def::Vector3) {
        self.base_mut().pos = pos;
    }

    fn set_rotation(&mut self, rot: data::math_def::Vector3) {
        self.base_mut().rot = rot;
    }
}
