use std::fmt::Display;

use bevy::prelude::Reflect;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use super::prelude::*;

#[derive(Clone, Default, Eq, PartialEq, Hash, Debug, Serialize, Deserialize, Reflect)]
pub struct CreatureState {
    pub damage: i32,
}

#[derive(
    Clone, Copy, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, Reflect,
)]
pub struct CreatureId(Uuid);

impl CreatureId {
    pub fn generate() -> Self {
        Self(Uuid::new_v4())
    }
}

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

#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize, Reflect)]
pub struct Creature {
    id: CreatureId,
    pub definition: CreatureDef,
    pub state: CreatureState,
}

impl Creature {
    pub fn generate_from_def(definition: CreatureDef) -> Self {
        Self {
            id: CreatureId::generate(),
            state: CreatureState::default(),
            definition,
        }
    }

    pub fn id(&self) -> CreatureId {
        self.id
    }

    pub fn patrol_chance(&self) -> f32 {
        if self.definition.patrols { 0.5 } else { 0.0 }
    }

    pub fn health(&self) -> i32 {
        self.definition.health - self.state.damage
    }

    pub fn is_alive(&self) -> bool {
        self.health() > 0
    }
}

impl Display for Creature {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{singular} ({hp}/{max_hp}) [{id}]",
            singular = self.definition.name_singular,
            hp = self.health(),
            max_hp = self.definition.health,
            id = self.id
        )
    }
}
