package org.project;

import org.project.entity.Entity;
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.consumables.Flask;
import org.project.item.consumables.Teriak;
import org.project.location.Location;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;

public class Main {

    public static final String RESET = "\u001B[0m";
    public static final String RED = "\u001B[31m";
    public static final String GREEN = "\u001B[32m";
    public static final String YELLOW = "\u001B[33m";
    public static final String BLUE = "\u001B[34m";


    public static Entity player;
    public static Entity enemy;
    public static Scanner input = new Scanner(System.in);
    public static ArrayList<Boolean> keys = new ArrayList<Boolean>();
    public static boolean running = true;


    public static void main(String[] args) {


        startMenu();

        while (running){  // when exit ruuning will be false

            do{

                try {             // if we have null location we handle with this try/catch
                    System.out.println("===============================");
                    Location fightLoc = fightMenu();                      // make location with random enemy
                    enemy = fightLoc.getEnemie();
                    System.out.println(enemy.toString() + "| HP:" + enemy.getHp());
                    System.out.println("Do you want fight?");
                    System.out.println("1.Yes");
                    System.out.println("2.No(Go to another location)");
                    int n = input.nextInt();
                    if(n==1){
                        gameplay();                  //  if you want play go to gameplay()
                        if(!player.isalive()){                    // result of match
                            System.out.println("===============================");
                            System.out.println( YELLOW + "Goodby!");
                            return;
                        }
                        else {
                            System.out.println(BLUE);
                            player.repair();
                            System.out.println(RESET);
                        }
                    }
                    else if(n >= 3){
                        System.out.println("Invalid input");
                    }
                }catch (NullPointerException exception){
                    System.out.println( YELLOW + "Goodby!");
                    return;
                }


            }while (running);



        }
    }

    //make keys array
    public static void setKeys(){           // set key array for enemies
        boolean goblinkey=false;
        boolean skeletonkey = false;
        boolean vampirekey = false;
        keys.add(goblinkey);
        keys.add(skeletonkey);
        keys.add(vampirekey);
    }

    /**
      this method choose for player in game
     */
    public static void startMenu(){
        System.out.println("----------Welcome to Java-Knight----------");
        setKeys();
        System.out.print("Please enter your name:");
        String name = input.next();
        System.out.println("Choose tor player:");
        System.out.println("1. ⚔\uFE0F Knight (High Damage)");
        System.out.println("2. \uD83E\uDDD9\u200D♂\uFE0F Wizard (High HP)");
        System.out.println("3. \uD83D\uDDE1\uFE0F️ Assassin (High Mana)");

        boolean validInput = false;       // check for vaild input
        while (!validInput){
            System.out.print("chose:");
            int choose =input.nextInt();
            switch (choose){
                case 1:
                {
                    player = new Knight(name);
                    validInput= true;
                    break;
                }
                case 2:
                {
                    player = new Wizard(name);
                    validInput = true;
                    break;
                }
                case 3:
                {
                    player = new Assassin(name);
                    validInput = true;
                    break;
                }
                default:
                {
                    System.out.println("Invalid input");
                    validInput = false;
                }
            }


        }
    }


    /**
     * make a location
     * @return location with random enemy
     */
    public static Location fightMenu(){
        boolean dragonOpen = true;    // check drangon is open
        for (Boolean b : keys){
            if(b == false){
                dragonOpen = false;
                break;
            }
        }


        System.out.println("Where do you want to go?");
        System.out.println("1.Desert");
        System.out.println("2.Sea");
        System.out.println("3.Jungle");

        for(boolean b : keys){      // for every key chek and write lock or tik
            if(b){
                System.out.print("✔\uFE0F");

            }
            else{
                System.out.print("🔒");
            }
        }




        if(dragonOpen) {
            System.out.println("4.Dranon");
        }
        else {
            System.out.println("Dragon");
        }

        System.out.println("0.EXIT (CLOSE GAME)");




        int n = (int) ((Math.random()) *3);     // a random number for random enemy
        Entity enemy = null;
        if(n == 0){
            enemy = new Goblin();
        }
        if(n==1){
            enemy = new Skeleton();
        }
        if(n==2){
            enemy = new Vampire();
        }

        Location location = null;


        boolean validInput = false;
        while (!validInput){
            System.out.print("chose:");
            int choose =input.nextInt();
            switch (choose){
                case 0:
                {
                    running = false;
                    return null;
                }
                case 1:
                {
                    location = new Location("Desert" , enemy);
                    validInput = true;
                    break;
                }
                case 2:
                {
                    location = new Location("Sea" , enemy);
                    validInput=true;
                    break;
                }
                case 3:
                {
                    location = new Location("Jungle" , enemy);
                    validInput =true;
                    break;
                }
                case 4:
                {
                    if(dragonOpen){
                        enemy = new Dragon();
                        location = new Location("The end of line" , enemy);
                        validInput = true;

                    }
                    else {
                        System.out.println("It's locked!!!!!!");
                        validInput = false;
                    }
                    break;
                }
                default:
                {
                    System.out.println("Invalid input");
                    validInput = false;
                    break;
                }

            }









        }
        System.out.println("===============================");
        return location;

    }


    /**
     * main loop of game
     */
    public static void gameplay(){
        boolean playerTurn = true;   // flag for check for turn

        while (player.isalive() && enemy.isalive()){


            System.out.println("=========================================");

            if(playerTurn){
                System.out.println(player.toString());
                System.out.println(enemy.toString() + "| HP:" + enemy.getHp());

                System.out.println("\n"+GREEN + "It's your Turn" +RESET);
                while (true){

                    if(playerAttakMenu()){    // maybe not enough mp and should choose again
                        break;
                    }

                }
                playerTurn = !playerTurn;


                // for skeleton relive
                if(enemy instanceof Skeleton && !enemy.isalive() && !((Skeleton) enemy).getResurrect()){
                    System.out.println("\n"+ RED);
                    enemy.specialAbility(player);
                    System.out.println(RESET);
                    playerTurn = !playerTurn;
                }
                // for win senario
                if(!enemy.isalive()){
                    System.out.println("you WIN");
                    int n = (int) (Math.random()*2);  // 50% present  enemy have key
                    if(enemy instanceof Dragon){
                        System.out.println(YELLOW + "Congratulation \n  You are the kingdom of Gogorio" +
                                "  1000 Hp | 1000 Mp" + RESET);
                        ((Player) player).setKing();           // king senario;
                    }


                    else if(n== 0){
                        if(enemy instanceof Goblin){
                            if(keys.get(0) == true){
                                System.out.println("You have got this key befor");
                                return;
                            }
                            keys.set(0, true);
                        }
                        else if (enemy instanceof Skeleton){
                            if(keys.get(1) == true){
                                System.out.println("You have got this key befor");
                                return;
                            }
                            keys.set(1 , true);
                        }
                        else if (enemy instanceof Vampire) {
                            if(keys.get(2) == true){
                                System.out.println("You have got this key befor");
                                return;
                            }
                            keys.set(2 , true);
                        }
                        System.out.println( YELLOW +"You chatck the" + enemy.toString() +"keys"+ RESET);
                    }
                    else {
                        System.out.println("There is no keys here");
                    }
                    return;
                }
            }


            if(!enemy.getpossible()){         // enemy is possible act?
                System.out.println(enemy.toString() + " Can't do any act");
                enemy.truepossible();
                playerTurn = !playerTurn;
                continue;
            }

            if(enemy.getpossible() && !playerTurn){

                System.out.println("\n" + RED +"It's  enemy Turn" + RESET);
                enemyAttakMenu();                 // randoum act from enemy;
                playerTurn = !playerTurn;
                
                
            }

            if(!player.isalive()){   // result
                System.out.println("you lose");
                return;
            }





        }



    }


    /**
     * selet a random act for each enemy
     */
    public static void enemyAttakMenu(){
        if(enemy instanceof Goblin || enemy instanceof Vampire){
            int n = (int) (Math.random()*3);
            if(n ==0 && enemy.getMp() >=10){
                enemy.specialAbility(player);
            }
            else if(n == 1){

                enemy.lightattack(player);
            }
            else {
                enemy.heavyattack(player);
            }

        }

        else if(enemy instanceof Skeleton){   // skeleton use special ability when he dead
            if(enemy.getHp() <= 0){
                enemy.heavyattack(player);
            }
            else {
                enemy.lightattack(player);
            }
        }

        else if( enemy instanceof Dragon){
            int n = (int)(Math.random()*3);
            if(n==0){
                enemy.specialAbility(player);
            }
            else {
                enemy.lightattack(player);
            }


        }


    }


    /**
     * choose a act for player
     * @return was the act successful or no
     */
    public static boolean playerAttakMenu() {

        System.out.print("1.Light attak|  ");
        System.out.print("2.Heavy attak("+player.getWeapon().getManaCost()+ " mana)|  ");
        System.out.print("3.Defend(12 mana)|  ");
        System.out.print("4.Heal(14 mana)|  ");
        System.out.println("5.Special action (30 mana)");

        int n ;

        while (true){
            System.out.print("choose:");
            n = input.nextInt();
            if(n > 0 && n < 6){
            break;
            }
            else {
                System.out.println("Invalid input");
            }
        }

        switch (n){
            case 1:
            {
                player.lightattack(enemy);
                return true;
            }
            case 2:
            {
                if(player.getMp() >= player.getWeapon().getManaCost()){
                    player.heavyattack(enemy);
                    return true;
                }
                else {
                    System.out.println("Not enough Mp");
                    return false;
                }
            }
            case 3:
            {
                if(player.getMp() >= 12){
                    player.defend();
                    return true;
                }
                else {
                    System.out.println("Not enough Mp");
                    return false;
                }
            }

            case 4:
            {
                if(player.getMp() >= 14){
                    System.out.println("1.Flask | 2. Teriak");
                    int k ;
                    while (true){
                        k = input.nextInt();
                        System.out.print("choose:");
                        if(k == 1){
                            Flask flask = new Flask();
                            flask.use(player);
                            break;
                        }
                        else if(k==2){
                            Teriak teriak = new Teriak();
                            teriak.use(player);
                            break;
                        }
                        else {
                            System.out.print("Invalid input");


                        }
                    }
                    return true;
                }
                else {
                    System.out.println("Not enough Mp");
                    return false;
                }

            }

            case 5:
            {
                if(player.getMp() >= 30){
                    player.specialAbility(enemy);
                    return true;
                }
                else {
                    System.out.println("Not enough Mp");
                    return false;
                }

            }
            default:
            {
                return false;
            }

        }

    }

}

