package org.project.entity.enemies;

import org.project.abilities.SpecialAbility;
import org.project.entity.Entity;
import org.project.entity.players.Player;
import org.project.item.armors.Armor;
import org.project.item.weapons.Weapon;
import org.project.managers.SpecialAbilityManager;
import org.project.managers.StatusEffectManager;
import org.project.weaponEffects.StatusEffect;

public abstract class Enemy implements Entity {

    // =========================================================
    // BASIC INFO
    // =========================================================

    private final String name;

    // =========================================================
    // STATS
    // =========================================================

    private int xpReward;

    private int maxHp;
    private int hp;

    private int maxMp;
    private int mp;

    private int baseDamage;

    // =========================================================
    // EQUIPMENT
    // =========================================================

    private Armor armor;
    private Weapon weapon;

    // =========================================================
    // ABILITIES
    // =========================================================

    private final SpecialAbility specialAbility;

    private final StatusEffectManager effectManager;
    private final SpecialAbilityManager abilityManager;

    // =========================================================
    // STATES
    // =========================================================

    private boolean defending;
    private boolean frozen;
    private boolean stunned;
    private boolean live;

    // =========================================================
    // CONSTRUCTOR
    // =========================================================

    public Enemy(
            String name,
            int maxHp,
            int maxMp,
            int xpReward,
            int baseDamage,
            Armor armor,
            Weapon weapon,
            SpecialAbility specialAbility
    ) {

        this.name = name;

        this.maxHp = maxHp;
        this.hp = maxHp;

        this.maxMp = maxMp;
        this.mp = maxMp;

        this.xpReward = xpReward;

        this.baseDamage = baseDamage;

        this.armor = armor;
        this.weapon = weapon;

        this.specialAbility = specialAbility;

        this.effectManager = new StatusEffectManager();
        this.abilityManager = new SpecialAbilityManager();
        this.live = true;
    }

    // =========================================================
    // XP REWARD
    // =========================================================

    public void rewardXp(Player player) {

        if (player == null) {
            return;
        }

        player.gainXp(xpReward);

        System.out.println(
                player.getName() +
                        " gained " +
                        xpReward +
                        " XP from defeating " +
                        name
        );
    }

    // =========================================================
    // STATUS EFFECTS
    // =========================================================

    @Override
    public void addStatusEffect(StatusEffect effect) {
        effectManager.addEffect(effect, this);
    }

    @Override
    public void tickStatusEffects() {
        effectManager.tick(this);
    }

    @Override
    public StatusEffectManager getEffectManager() {
        return effectManager;
    }

    // =========================================================
    // ABILITIES
    // =========================================================

    @Override
    public void addAbilityEffect(SpecialAbility ability, Entity target) {
        abilityManager.addAbility(ability, target);
    }

    @Override
    public void tickAbilityEffects(Entity target) {
        abilityManager.tick(this, target);
    }

    @Override
    public SpecialAbility getSpacialAbility() {
        return specialAbility;
    }

    // =========================================================
    // COMBAT
    // =========================================================

    @Override
    public void takeDamage(int amount) {

        int finalDamage = Math.max(0, amount);

        hp -= finalDamage;
        if (hp <= 0) {
            hp = 0;
            live = false;
        }
    }

    @Override
    public void heal(int amount) {

        if (!live) {
            return;
        }

        hp += amount;
        if (hp > maxHp) {
            hp = maxHp;
            System.out.println("HP reached maximum amount " + maxHp);
        }
    }

    @Override
    public void useMana(int amount) {

        if (amount <= 0) {
            return;
        }

        if (mp < amount) {

            System.out.println(name + " doesn't have enough mana!");
            return;
        }

        mp -= amount;
    }

    @Override
    public void defend() {
        defending = true;
    }


    // =========================================================
    // STATES
    // =========================================================


    @Override
    public boolean isDefending() {
        return defending;
    }

    @Override
    public boolean isFrozen() {
        return frozen;
    }

    public boolean isStunned() {return stunned;}

    @Override
    public void freeze() {
        frozen = true;
    }

    public void stun() {
        stunned = true;
    }

    @Override
    public void resetTurnState() {

        defending = false;
        frozen = false;
        stunned = false;
    }

    // =========================================================
    // GETTERS
    // =========================================================

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getHp() {
        return hp;
    }

    @Override
    public int getMp() {
        return mp;
    }

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

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

    @Override
    public int getBaseDamage() {
        return baseDamage;
    }

    @Override
    public Weapon getWeapon() {
        return weapon;
    }

    @Override
    public Armor getArmor() {
        return armor;
    }

    @Override
    public Armor getPersonalArmor() {
        return armor;
    }

    public boolean isLive() {
        return live;
    }

    public int getXpReward() {
        return xpReward;
    }

    // =========================================================
    // SETTERS
    // =========================================================

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

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

    @Override
    public void setHp(int value) {
        hp = Math.max(0, Math.min(value, maxHp));
    }

    @Override
    public void setMp(int value) {
        mp = Math.max(0, Math.min(value, maxMp));
    }

}
