use rd::util::types::*;
use rd::actor::Actor;

pub struct Player {
    position: usize,
    experience: Experience,
    exp_to_level_up: Experience,
    level: Level,
    hp: Health,
    max_hp: Health,
    attack: Attack,
}

pub const MAX_LEVEL: Level = 10;
const EXP_PER_LEVEL: Experience = 5;
const HP_PER_LEVEL: Health = 10;

impl Actor for Player {
    fn get_level(&self) -> Level {
        self.level
    }

    fn get_max_hp(&self) -> Health {
        self.max_hp
    }

    fn get_hp(&self) -> Health {
        self.hp
    }

    fn get_position(&self) -> MapIndex {
    pub fn spawn_at(spawn_point: MapIndex) -> Player {
        Player {
            position: spawn_point,
            experience: 0,
            exp_to_level_up: EXP_PER_LEVEL,
            level: 1,
            hp: 10,
            max_hp: 10,
            attack: 5,
        }
    }

    pub fn move_to(&mut self, tile: MapIndex) {
        self.position = tile;
        dbg!("Player moved to {}", tile);
    }

    pub fn get_exp(&self) -> Experience {
        self.experience
    }

    pub fn get_exp_needed_to_level_up(&self) -> Experience {
        self.exp_to_level_up
    }

    pub fn grant_exp(&mut self, exp: Experience) {
        self.experience += exp;
        dbg!("Granted {} EXP.", exp);

        if self.levelled_past_max() {
            self.experience -= self.exp_to_level_up;
            self.restore_full_hp();
            return;
        }

        while self.experience >= self.exp_to_level_up {
            self.level_up();
            self.exp_to_level_up += EXP_PER_LEVEL;
        }
    }

    #[cfg(test)]
    pub fn damage(&mut self, damage_points: Health) {
        self.hp -= damage_points;
    }

    fn level_up(&mut self) {
        self.level += 1;
        self.experience -= self.exp_to_level_up;
        self.max_hp += HP_PER_LEVEL;
        self.attack += 5;
        dbg!("LEVEL UP to {}", self.level);
        self.restore_full_hp();
    }

    fn restore_full_hp(&mut self) {
        self.hp = self.max_hp;
        dbg!("HP fully restored.");
    }

    fn levelled_past_max(&self) -> bool {
        self.level == MAX_LEVEL && self.experience >= self.exp_to_level_up
    }
    pub fn get_attack(&self) -> Attack {
        self.attack
    }

}
        self.position
    }
}

impl Player {