package org.project.entity.players;

import org.project.entity.Entity;
import org.project.entity.enemies.Enemy;
import org.project.entity.enemies.Goblin;
import org.project.entity.enemies.Skeleton;
import org.project.entity.enemies.Vampire;
import org.project.item.armors.Armor;
import org.project.item.potions.Potion;
import org.project.item.weapons.Weapon;

import java.util.ArrayList;
import java.util.List;

public abstract class Player implements Entity{
    protected String name;
    Weapon weapon;
    Armor armor;

    private ArrayList<Potion> potions = new ArrayList<Potion>();
    private ArrayList<Weapon> weapons = new ArrayList<Weapon>();
    private ArrayList<Armor> armors = new ArrayList<Armor>();

    private int hp;
    private int maxHP;
    private int mp;
    private int maxMP;

    private boolean isDefending;
    private boolean isInvisible;
    private boolean CHitOnNextTurn;

    private int coins;

    private int xp;
    private static int maxXP = 70;
    private int level;

    private boolean goblinKey;
    private boolean skeletonKey;
    private boolean vampireKey;
    private boolean threeKeys;

    private static int heavyAttackMana = 8;
    private static int defendMana = 6;
    private static int healMana = 12;
    private static int specialAbilityMana = 15;

    public Player(String name, int hp, int mp,
                  Weapon weapon, Armor armor,
                  int maxHP, int maxMP) {
        this.weapons.add(weapon);
        this.armors.add(armor);

        this.name = name;
        this.hp = hp;
        this.mp = mp;

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

        this.maxMP = maxMP;
        this.maxHP = maxHP;
        this.coins = 0;
    }

    public void earnCoins(int extraCoins) { coins += extraCoins; }

    public void grabTheKey(Enemy enemy) {
        if (enemy instanceof Goblin) { goblinKey = true; }
        else if (enemy instanceof Skeleton) { skeletonKey = true; }
        else if (enemy instanceof Vampire) { vampireKey = true; }

        if (goblinKey && skeletonKey && vampireKey) { threeKeys = true; }
    }

    public boolean keyStatus(Enemy enemy) {
        if (enemy instanceof Goblin) { return goblinKey; }
        else if (enemy instanceof Skeleton) { return skeletonKey; }
        else if (enemy instanceof Vampire) { return vampireKey; }
        return false;
    }

    public boolean threeKeys() { return threeKeys; }

    public void levelUp() {
        maxHP += 10;
        maxMP += 10;
    }
    public void increaseXP(int addedXP) {
        if (addedXP + xp >= maxXP) {
            level++;
            levelUp();
            xp += addedXP - maxXP;
        }
        else {
            xp += addedXP;
        }
    }

    @Override
    public void attack(Entity target) {
        target.takeDamage(7);
        if (CHitOnNextTurn) {
            target.takeDamage(15);
            CHitOnNextTurn = false;
        }
    }

    public boolean heavyAttack(Entity target) {
        if (mp >= 8) {
            mp -= 8;
            target.takeDamage(weapon.getDamage());
            if (CHitOnNextTurn) {
                target.takeDamage(weapon.getDamage() + 5);
                CHitOnNextTurn = false;
            }
            return true;
        }
        else return false;
    }

    public boolean defend(Entity target) {
        if (mp >= 6) {
            mp -= 6;
            if (CHitOnNextTurn) {
                target.takeDamage(weapon.getDamage() + 5);
                CHitOnNextTurn = false;
            }
            isDefending = true;
            return true;
        }
        return false;
    }

    @Override
    public void takeDamage(int damage) {
        if (isInvisible) {
            isInvisible = false;
            return;
        }
        if (isDefending) {
            if (damage > armor.getDefense()) {
                hp -= damage - armor.getDefense();
                armor.decreaseDurability();
                armor.checkBreak();
                isDefending = false;
            }
        }
        else {
            hp -= damage;
        }
    }

    public void heal(Enemy target, int health) {
        if (CHitOnNextTurn) {
            target.takeDamage(weapon.getDamage() + 5);
            CHitOnNextTurn = false;
        }
        hp += health;
        if (hp > maxHP) {
            hp = maxHP;
        }
    }

    public boolean specialAbility(Player player, Enemy target) { return false; }

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

    @Override
    public boolean isAlive() {
        if (hp <= 0) {
            return false;
        }
        return true;
    }

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

    public void victory(Enemy enemy) {
        increaseXP(enemy.getXpPrize());
        earnCoins(enemy.getCoinPrize());
        hp = maxHP;
        mp = maxMP;
    }

    public void failure() {
        level = 0;
        xp = 0;
        mp = maxMP;
        hp = maxHP;
        goblinKey = false;
        skeletonKey = false;
        vampireKey = false;
        threeKeys = false;
    }

    public boolean pay(int cost) {
        if (cost <= coins) {
            coins -= cost;
            return true;
        }
        return false;
    }

    public void removePotion(Potion p) { potions.remove(p); }

    public int potionsNumber() { return potions.size(); }

    public boolean addItem(Potion p, int cost) {
        boolean res = pay(cost);
        if (res) {
            potions.add(p);
        }
        return res;
    }

    public boolean addItem(Weapon w, int cost) {
        boolean res = pay(cost);
        if (res) {
            weapons.add(w);
        }
        return res;
    }

    public boolean addItem(Armor a, int cost) {
        boolean res = pay(cost);
        if (res) {
            armors.add(a);
        }
        return res;
    }

    public void setWeapon(Weapon w) { weapon = w; }

    public void setArmor(Armor a) { armor = a; }

    public void spendMP(int MP) { mp -= MP; }

    public String getName() { return name; }

    public int getMaxHP() { return maxHP; }

    public int getMP() { return mp; }

    public int getMaxMP() { return maxMP; }

    public Weapon getWeapon() { return weapon; }

    public Armor getArmor() { return armor; }

    public int getLevel() { return level; }

    public int getXP() { return xp; }

    public int getMaxXP() { return maxXP; }

    public int getCoins() { return coins; }

    public List<Potion> getPotionsList() { return potions; }

    public List<Weapon> getWeaponsList() { return weapons; }

    public List<Armor> getArmorsList() { return armors; }

    public void turnInvisible() { isInvisible = true; }

    public void CHitOnNextTurn(boolean t) { CHitOnNextTurn = t; }

    public boolean isCHitOnNextTurn() { return CHitOnNextTurn; }
}
