import org.project.Colors;
import org.project.entity.enemies.*;
import org.project.entity.players.Assassin;
import org.project.entity.players.Knight;
import org.project.entity.players.Player;
import org.project.entity.players.Wizard;
import org.project.item.armors.AssassineArmor;
import org.project.item.armors.KnightArmor;
import org.project.item.armors.WizardArmor;
import org.project.item.consumables.*;
import org.project.item.weapons.AssassineWeapon;
import org.project.item.weapons.Sword;
import org.project.item.weapons.WizardWeapon;
import org.project.location.Location;

import javax.swing.plaf.metal.MetalRootPaneUI;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        // TODO: ADD LOCATIONS TO YOUR GAME
        List<Location> locations = new ArrayList<>();
        Location loc1 = new Location("Darkmire Hollow");
        loc1.addEnemy(new Goblin());

        Location loc2 = new Location("Grave of the Fallen");
        loc2.addEnemy(new Skeleton());
        Location loc3 = new Location("Goblin Warrens");
        loc3.addEnemy(new Goblin());

        Location loc4 = new Location("Vampire's Embrace");
        loc4.addEnemy(new Vampire());


        Location loc5 = new Location("Blightmoor Cave");
        loc5.addEnemy(new Goblin());
        loc5.addEnemy(new Skeleton());

        Location loc6 = new Location("Crypt of Bleeding  Bones");
        loc6.addEnemy(new Vampire());
        loc6.addEnemy(new Skeleton());

        Location loc7 = new Location("Cackling Caverns");
        loc7.addEnemy(new Goblin());
        loc7.addEnemy(new Goblin());
        loc7.addEnemy(new Goblin());

        Collections.addAll(locations, loc1, loc2, loc3, loc4, loc5, loc6, loc7);
        List<Consumable> allItems = new ArrayList<>();
        Collections.addAll(allItems, new CursedDagger(), new ElixirOfLife(), new GoblinGland(), new HealthPotion(), new HolyWater(), new ManaPotion());

        // TODO: IMPLEMENT GAMEPLAY
        System.out.print(Colors.RESET + "enter your name: ");
        Scanner in = new Scanner(System.in);
        String name = in.next();
        System.out.println("Choos your character: ");
        System.out.println("1.Knight: ");
        System.out.println("2.Assassine");
        System.out.println("3.Wizard");
        Player player = null;
        int input2 = in.nextInt();
        while (input2 > 3 || input2 < 1)
        {
            System.out.println("invalid input!");
            System.out.println("Choos your character: ");
            System.out.println("1.Knight");
            System.out.println("2.Assassine");
            System.out.println("3.Wizard");
            input2 = in.nextInt();
        }
        switch (input2)
        {
            case (1):
            {
                player = new Knight(name, new Sword(), new KnightArmor());
                break;
            }
            case(2):
            {
                player = new Assassin(name, new AssassineWeapon(), new AssassineArmor());
                break;
            }
            case(3):
            {
                player = new Wizard(name, new WizardWeapon(), new WizardArmor());
                break;
            }
        }
        player.showInf();
        System.out.println(Colors.YELLO + "WELCOME\n" + Colors.RESET);

        boolean running = true;
        while (running)
        {
            Location randomLoc = locations.get(new Random().nextInt(7));
//            while (randomLoc.isDiscovered())
//            {
//                randomLoc = locations.get(new Random().nextInt());
//            }
            System.out.println(randomLoc);
            System.out.println("1.Fight the enemies");
            System.out.println("2.Move to another location");
            System.out.println("3.Visit Merchant");

            boolean hasKeys = player.getGoblinKey() && player.getSkeletonKey() && player.getVampireKey();
            if(hasKeys)
            {
                System.out.println("4.Go to the Castle to fight the Dragon");
            }


            int input = in.nextInt();
            while((input > 4 || input < 1))
            {
                System.out.println("input is invalid!");
                System.out.println(randomLoc);
                System.out.println("1.Fight the enemies");
                System.out.println("2.Move to another location");
                System.out.println("3.Visit Merchant");

                if(hasKeys)
                {
                    System.out.println("4.Go to the Castle to fight the Dragon");
                }
                in.next();
                input = in.nextInt();
            }
            switch (input)
            {
                case (1):
                {
                    if(randomLoc.getEnemies().size() > 1)
                    {
                        System.out.println("You have to fight with " + randomLoc.getEnemies().size() + " enemies!");
                        System.out.println("How Brave you are!");
                        System.out.println(Colors.YELLO + "Have luck" + Colors.RESET);
                    }
                    //or && running?
                    while (randomLoc.checkLives() && player.isAlive())
                    {
                        for (int i = 0; i < randomLoc.getEnemies().size(); i++) {
                            Enemy currentEnemy = randomLoc.getEnemies().get(i);
                            System.out.println("You know have to fight with " + currentEnemy.getClass().getSimpleName());
                            if (combat(player, currentEnemy))
                            {
//                                randomLoc.defeatEnemy(currentEnemy);
                                if (player.needLevelUp()) {
                                    player.levelUp();
                                }
                            }
                            else
                            {
                                running = false;
                                break;
                            }
                        }

                    }
                    if(player.isAlive())
                    {
                        player.setHp(player.getMaxHP());
                        player.fillMana(player.getMaxMP());
                        player.getArmor().repair();
                        randomLoc.resetLives();
                    }
                    break;
                }
                case(2):
                {
                    break;
                }
                case(3):
                {
                    System.out.println(Colors.WELCOME + "Welcome, traveler!" + Colors.RESET);
                    int input4;
                    do
                    {
                        for (int i = 0; i < allItems.size(); i++) {
                            System.out.println((i + 1) + "." + allItems.get(i));
                        }
                        System.out.println(Colors.ORANGE + "[" + Colors.RESET + "Your coins: " + Colors.COIN + player.getCoin() + Colors.ORANGE + "]" + Colors.RESET);
                        System.out.println("Which one do you want to buy?");
                        System.out.println("enter your choice(write 0 to back): ");
                        input4 = in.nextInt();
                        if(input4 < 0 || input4 > allItems.size())
                        {
                            System.out.println("invalid input!");
                            continue;
                        }
                        switch (input4) {
                            case (0): {
                                break;
                            }
                            case (1): {
                                if (allItems.get(0).getValue() <= player.getCoin()) {
                                    player.addItem(allItems.get(0));
                                    player.setCoin(player.getCoin() - allItems.get(0).getValue());
                                    break;
                                }
                            }
                            case (2): {
                                if (allItems.get(1).getValue() <= player.getCoin()) {
                                    player.addItem(allItems.get(1));
                                    player.setCoin(player.getCoin() - allItems.get(1).getValue());
                                    break;
                                }
                            }
                            case (3): {
                                if (allItems.get(2).getValue() <= player.getCoin()) {
                                    player.addItem(allItems.get(2));
                                    player.setCoin(player.getCoin() - allItems.get(2).getValue());
                                    break;
                                }
                            }
                            case (4): {
                                if (allItems.get(3).getValue() <= player.getCoin()) {
                                    player.addItem(allItems.get(3));
                                    player.setCoin(player.getCoin() - allItems.get(3).getValue());
                                    break;
                                }
                            }
                            case (5): {
                                if (allItems.get(4).getValue() <= player.getCoin()) {
                                    player.addItem(allItems.get(4));
                                    player.setCoin(player.getCoin() - allItems.get(4).getValue());
                                    break;
                                }
                            }
                            case (6): {
                                if (allItems.get(5).getValue() <= player.getCoin()) {
                                    player.addItem(allItems.get(5));
                                    player.setCoin(player.getCoin() - allItems.get(5).getValue());
                                    break;
                                }
                            }
                            default: {
                                System.out.println("You don't have enough coin!");
                            }
                        }
                    }while (input4 != 0 );
                }
                case(4):
                {
                    if(hasKeys)
                    {
                        if (combat(player, new Dragon()))
                        {
                            System.out.println(Colors.PINK + "VICTORY!!!!!!!");
                            running = false;
                        }
                        else
                        {
                            running = false;
                            break;
                        }
                    }
                }

            }
        }
    }
    public static boolean combat(Player p, Enemy e)
    {
        int round = 0;
        while (p.isAlive() && e.isAlive())
        {
//            System.out.println("You choos to fight with " + e.getClass().getSimpleName());
            System.out.printf(Colors.ORANGE + "[" + Colors.RESET + p.getName() + " - " +"%d/%d HP | %d/%d Mana" + Colors.ORANGE + "]\n" ,
                    p.getHp(), p.getMaxHP(), p.getMp(), p.getMaxMP());
            System.out.printf(Colors.ORANGE + "[" + Colors.RESET + e.getClass().getSimpleName() + " - " +"%d/%d HP" + Colors.ORANGE + "]\n" + Colors.RESET, e.getHp(), e.getMaxHP() );
            System.out.println("Your turn:");
            switch (p) {
                case Knight knight ->
                        System.out.println("1.Light Attack | 2.Heavy Attack " + Colors.ORANGE + "(" + Colors.RESET + "-50 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 3.Defend " + Colors.ORANGE + "(" + Colors.RESET + "-40 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 4.Heal" + Colors.ORANGE + "(" + Colors.RESET + "-45 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 5.Shield Bash " + Colors.ORANGE + "(" + Colors.RESET + "-65 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")\n" + Colors.RESET);
                case Assassin assassin ->
                        System.out.println("1.Light Attack | 2.Heavy Attack " + Colors.ORANGE + "(" + Colors.RESET + "-55 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 3.Defend " + Colors.ORANGE + "(" + Colors.RESET + "-40 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 4.Heal" + Colors.ORANGE + "(" + Colors.RESET + "-45 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 5.Shadow Strike " + Colors.ORANGE + "(" + Colors.RESET + "-80 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")\n" + Colors.RESET);
                case Wizard wizard ->
                        System.out.println("1.Light Attack | 2.Heavy Attack " + Colors.ORANGE + "(" + Colors.RESET + "-65 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 3.Defend " + Colors.ORANGE + "(" + Colors.RESET + "-40 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 4.Heal" + Colors.ORANGE + "(" + Colors.RESET + "-45 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")" +
                                Colors.RESET + " | 5.Blood Burn " + Colors.ORANGE + "(" + Colors.RESET + "-75 " + Colors.BLUE + "Mana" + Colors.ORANGE + ")\n" + Colors.RESET);
                default -> {

                }
            }
            if(!p.getItems().isEmpty())
            {
                System.out.println("press 6 to see your items.");
            }
            Scanner input = new Scanner(System.in);
            int input3 = input.nextInt();
            switch (input3)
            {
                case(1):
                {
                    p.lightAttack(e);
                    break;
                }
                case(2):
                {
                    if(!p.heavyAttack(e))
                    {
                        continue;
                    }
                    break;
                }
                case(4):
                {
                    if(!p.heal(p.getMaxHP()))
                    {
                        continue;
                    }
                    break;
                }
                case(5):
                {
                    if(!p.specialAbility(e))
                    {
                        continue;
                    }
                    break;
                }
                case(6):
                {
                    if(!p.getItems().isEmpty())
                    {
                        p.showItems();
                        System.out.println("What do you want to use: ");
                        System.out.println("press 0 to back.");
//                        System.out.println(p);
                        int input5 = input.nextInt();
                        while (input5 < 0 || input5 > p.getItems().size())
                        {
                            System.out.println("invalid input!");
                            p.showItems();
                            System.out.println("What do you want to use: ");
                            System.out.println("press 0 to back.");
                            input5 =input.nextInt();
                        }
                        if(input5 == 0)
                        {
                            continue;
                        }
                        else
                        {
                            if(p.getItems().get(input5 - 1).getTargetType().equals("Player"))
                            {
                                p.getItems().get(input5 - 1).use(p);

                            }
                            else
                            {
                                if(p.getItems().get(input5 - 1) instanceof GoblinGland)
                                {
                                    p.getItems().get(input5 - 1).use(e);
                                    continue;
                                }
                                p.getItems().get(input5 - 1).use(e);
                            }
                            p.useItem(p.getItems().get(input5 - 1));
                        }
                    }
                    break;
                }
            }
            if(e.isAlive())
            {

                if(e.isConfuse())
                {
                    System.out.println("Enemy lost its turn cause of confusion");
                    continue;
                }
                if (input3 == 5 && p instanceof Knight)
                {
                    System.out.printf("%s couldn't do anything in his round\n", e.getClass().getSimpleName());
                    continue;
                }
                if(e.HaveBleed())
                {
//                    System.out.println(e.getClass().getSimpleName() + " is " + Colors.RED + "Bleeding!\n" + Colors.RESET);
                    e.bleed((AssassineWeapon) p.getWeapon());
                }
                System.out.printf("%s" + "'s turn:\n", e.getClass().getSimpleName());
                if (input3 == 3) {
                    p.defend(e.attack());
                }
                else
                {
                    if(e instanceof Dragon)
                    {
                        p.takeDamage((Dragon) e);

                    }
                    else if(p instanceof Wizard w) {
                        w.takeDamage(e ,e.attack());
                    }
                    else
                    {
                        p.takeDamage(e.attack());
                    }
                }
                if(!p.isAlive())
                {
                    System.out.println("You " + Colors.RED + "Died" + Colors.BLUE + ":(");
                    return false;
                }
                round++;
                if(round == 2)
                {
                    round = 0;
                    if (p instanceof Knight) {
                        p.fillMana(p.getMaxMP() / 5);
                    } else {
                        p.fillMana(p.getMaxMP() / 10);
                    }
                }
            }
            else
            {
                System.out.println("You defeat the " + e.getClass().getSimpleName());
                p.addXp(e);
                p.addCoin(e);
                e.dropKey(p);
                System.out.println("Keep moving forward!");
                System.out.println("Good luck!");
                return true;
            }

        }
        return false;
    }
}
