package rip.tilly.bedwars.upgrades;

import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import rip.tilly.bedwars.game.Game;
import rip.tilly.bedwars.game.GameTeam;
import rip.tilly.bedwars.playerdata.currentgame.PlayerCurrentGameData;
import rip.tilly.bedwars.utils.CC;
import rip.tilly.bedwars.utils.ItemBuilder;

import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import java.util.stream.Collectors;

public class UpgradeItem {

    private String name;

    private String[] lore;

    private Material material;

    private Upgrade upgrade;

    public UpgradeItem(String name, String[] lore, Material material, Upgrade upgrade) {
        this.name = name;
        this.lore = lore;
        this.material = material;
        this.upgrade = upgrade;
    }

    public ItemStack getItemStack(Player player, PlayerCurrentGameData playerCurrentGameData) {
        int level = playerCurrentGameData.getLevelForUpgrade(this.upgrade);

        ItemBuilder itemBuilder = new ItemBuilder(this.material, Math.min(level + 1, this.upgrade.getHighestLevel()));
        itemBuilder.name(CC.translate("&e" + this.name + " " + this.upgrade.getNumberToRomanNumeral(Math.min(level + 1, this.upgrade.getHighestLevel()))));

        List<String> lore = Arrays.stream(this.lore).map(line -> "&7" + line).collect(Collectors.toList());
        lore.add(CC.translate(""));

        if (this.upgrade.getHighestLevel() == 1) {
            lore.add(CC.translate("&7Cost: &b" + this.upgrade.getCostForLevel(1) + " Diamond" + (this.upgrade.getCostForLevel(1) == 1 ? "" : "s")));
        } else {
            for (int i = 0; i < this.upgrade.getHighestLevel(); i++) {
                int amount = i + 1;

                String string = this.upgrade.getCostForLevel(amount) + " Diamond" + (this.upgrade.getCostForLevel(amount) == 1 ? "" : "s");

                lore.add(CC.translate((level < amount ? "&7" : "&a") + "Tier " + amount + ": " + this.upgrade.getPerkForLevel(amount) + ", &b" + string));
            }
        }

        lore.add(CC.translate(""));

        if (playerCurrentGameData.getCostToUpgrade(this.upgrade) != -1) {
            if (this.canBuy(player, level + 1)) {
                lore.add(CC.translate("&aClick to purchase"));
            } else {
                lore.add(CC.translate("&cNot enough diamonds"));
            }
        } else {
            lore.add(CC.translate("&aUnlocked"));
        }

        itemBuilder = itemBuilder.lore(lore);

        return itemBuilder.build();
    }

    public void buy(Player player, int level, Game game, GameTeam gameTeam, PlayerCurrentGameData playerCurrentGameData) {
        if (!this.canBuy(player, level)) {
            return;
        }

        int price = this.upgrade.getCostForLevel(level);
        int removed = 0;

        for (ListIterator<ItemStack> listIterator = player.getInventory().iterator(); listIterator.hasNext();) {
            ItemStack itemStack = listIterator.next();

            if (itemStack != null && itemStack.getType() == Material.DIAMOND) {
                if (itemStack.getAmount() >= price) {
                    removed += itemStack.getAmount() - price;

                    itemStack.setAmount(itemStack.getAmount() - price);
                } else {
                    removed += itemStack.getAmount();

                    itemStack.setAmount(0);
                }

                if (price <= removed) {
                    break;
                }
            }
        }

        playerCurrentGameData.upgrade(player, game, gameTeam, this.upgrade);
    }

    public boolean canBuy(Player player, int level) {
        int amount = 0;

        for (ListIterator<ItemStack> listIterator = player.getInventory().iterator(); listIterator.hasNext();) {
            ItemStack itemStack = listIterator.next();

            if (itemStack != null && itemStack.getType() == Material.DIAMOND) {
                amount += itemStack.getAmount();
            }
        }

        return amount >= this.upgrade.getCostForLevel(level);
    }

    public Upgrade getUpgrade() {
        return this.upgrade;
    }
}
