package org.project.entity.players;

import org.project.entity.Entity;
import org.project.item.armors.Armor;
import org.project.item.weapons.Weapon;

// TODO: UPDATE IMPLEMENTATION
public abstract class Player implements Entity {
    protected String name;
    private Weapon weapon;
    Armor armor;
    private int hp;
    private int maxHP;
    private int mp;
    private int maxMP;
    private int level;
    private boolean isAlive;
    private String playerClass;
    private int XP;
    private int XPNeedToNextLevel;
    private int baseDamage;
    private int specialDamage;
    private boolean hasGoblinKey;
    private boolean hasSkeletonkey;
    private boolean hasVampireKey;
    private boolean isDefending;

    public Player(String name, int hp, int mp, Weapon weapon, Armor armor, String playerClass, int XP,
                   int maxHP, int maxMP) {
        this.name = name;
        this.hp = hp;
        this.mp = mp;

        this.weapon = weapon;
        this.armor = armor;
        this.playerClass = playerClass;
        this.XP = XP;
        this.maxHP = maxHP;
        this.maxMP = maxMP;
        this.level = 1;
        this.XPNeedToNextLevel = 100;
        this.isAlive = true ;
        this.baseDamage = weapon !=null ? weapon.getDamage() : 10;
        this.hasGoblinKey = false;
        this.hasSkeletonkey = false;
        this.hasVampireKey = false;
    }

    @Override
    public void attack(Entity target) {
        target.takeDamage(weapon.getDamage());
    }

    @Override
    public void defend()
    {
       // TODO
        this.isDefending = true ;
        System.out.println(name + " is defending ");
    }


    @Override
    public void takeDamage(int damage) {
        if (isDefending)
        {
            damage /= 2;
            isDefending = false;
            System.out.println("Defense halved the damage to " + damage + "!");
        }
        if (armor != null)
        {
            int finalDamage = damage - armor.getDefense();
            if (finalDamage >= 0)
                hp -= finalDamage;
        }
        else
            hp -= damage;
        if (hp <= 0)
        {
            isAlive = false;
            hp = 0;
        }
    }

    @Override
    public void heal(int health) {
        hp += health;
        if (hp > maxHP) {
            hp = maxHP;
        }
    }

    @Override
    public void fillMana(int mana) {
        mp += mana;
        if (mp > maxMP) {
            mp = maxMP;
        }
    }


    public String getName() {
        return name;
    }

    public int getHP() {
        return hp;
    }

    @Override
    public int getMaxHP() {
        return maxHP;
    }

    public int getMP() {
        return mp;
    }

    @Override
    public int getMaxMP() {
        return maxMP;
    }

    public Weapon getWeapon() {
        return weapon;
    }

    public void setWeapon(Weapon weapon)
    {
        this.weapon = weapon;
    }

    public Armor getArmor() {
        return armor;
    }

    public void setArmor(Armor armor)
    {
        this.armor = armor;
    }

    public int level()
    {
        return level;
    }

    @Override
    public boolean isAlive()
    {
        return isAlive;
    }

    public abstract void lightAttack(Entity target);
    public abstract void specialAbility(Entity target);
    public abstract void heavyAttack(Entity target);

    public String getPlayerClass()
    {
        return playerClass;
    }
    public void gainXp(int amount) {
        this.XP += amount;
        System.out.println(amount + " XP! (Total: " + XP + "/" + XPNeedToNextLevel + ")");

        while (XP >= XPNeedToNextLevel) {
            XP -= XPNeedToNextLevel;
            level++;
            int oldMaxHP = maxHP;
            int oldMaxMP = maxMP;
            maxHP += 15;
            maxMP += 10;
            hp = maxHP;
            mp = maxMP;
            XPNeedToNextLevel = level * 100;

            System.out.println(" LEVEL UP! Now level " + level + "! 🎉");
            System.out.println("  HP: " + oldMaxHP + " → " + maxHP);
            System.out.println("  MP: " + oldMaxMP + " → " + maxMP);
        }
    }

    public void restoreAfterBattle() {
        hp = maxHP;
        mp = maxMP;
        System.out.println(name + " fully restored!");
        System.out.println("   HP: " + hp + "/" + maxHP + " | MP: " + mp + "/" + maxMP);
    }

    public boolean hasGoblinKey() { return hasGoblinKey; }
    public boolean hasSkeletonKey() { return hasSkeletonkey; }
    public boolean hasVampireKey() { return hasVampireKey; }

    public void addGoblinKey() { hasGoblinKey = true; }
    public void addSkeletonKey() { hasSkeletonkey = true; }
    public void addVampireKey() { hasVampireKey = true; }

    public boolean hasAllKeys() {
        return hasGoblinKey && hasSkeletonkey && hasVampireKey;
    }

    public int getXP() {
        return XP;
    }

    public int getXPNeedToNextLevel() {
        return XPNeedToNextLevel;
    }

}
