using Assets.Scripts.Classes;
using Assets.Scripts.Races;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Assets.Scripts
{
    public class UIHandler : MonoBehaviour
    {
        public GameObject map;
        public GameObject compass;
        public GameObject information;
        public GameObject fight;
        public GameObject message;
        public GameObject charactersheet;
        public GameObject deathscreen;
        public GameObject mainMenu;
        public GameObject options;
        public GameObject characterCreation;
        public GameObject pauseMenu;
        public GameObject playerHUD;
        public GameObject questlog;
        public GameObject tutorial;
        public GameObject tooltip;

        public UIState state;

        // Start is called before the first frame update
        void Start()
        {
            options.SetActive(false);
            hideOtherElements(mainMenu);
            state = UIState.MAINMENU;
        }

        // Update is called once per frame
        void Update()
        {
            if (state == UIState.GAME)
            {
                updatePlayerHUD();
                Cursor.visible = false;
            }
            else
            {
                if (state != UIState.FIGHT && state != UIState.MAP && state != UIState.QUEST)
                {
                    Cursor.visible = true;
                }
            }
        }

        private void updatePlayerHUD()
        {
            updateHUD(GameObject.Find("Player").GetComponent<Player>());
        }

        public bool canPlayerMove()
        {
            if (state == UIState.GAME || state == UIState.MAP || state == UIState.CHARACTER || state == UIState.QUEST)
            {
                return true;
            }
            return false;
        }

        public bool isPlayerInFight()
        {
            return state == UIState.FIGHT;
        }

        public void startGame()
        {
            int index = GameObject.Find("dropSize").GetComponent<Dropdown>().value;
            int cityAmount = 0;
            switch (index)
            {
                case 0:
                    cityAmount = 5;
                    break;
                case 1:
                    cityAmount = 10;
                    break;
                case 2:
                    cityAmount = 20;
                    break;
                case 3:
                    cityAmount = 40;
                    break;
            }
            GameObject.Find("WorldGenerator").GetComponent<WorldGenerator>().resetGame(cityAmount);
            setPlayerInformation();
            tutorial.transform.localScale = new Vector3(0,0,0);
            compass.transform.localScale = new Vector3(1, 1, 1);
            showHUD();
            state = UIState.GAME;
            EventSystem.current.SetSelectedGameObject(null);
        }

        private void setPlayerInformation()
        {
            string name = GameObject.Find("inName").GetComponent<InputField>().text;
            int role = GameObject.Find("dropClass").GetComponent<Dropdown>().value;
            int race = GameObject.Find("dropRace").GetComponent<Dropdown>().value;
            BasicRace playerRace = new BasicRace();
            BasicClass playerClass = new BasicClass();
            switch (role)
            {
                case 0:
                    playerClass = new WarriorClass();
                    break;
                case 1:
                    playerClass = new MageClass();
                    break;
                case 2:
                    playerClass = new ThiefClass();
                    break;
            }
            switch (race)
            {
                case 0:
                    playerRace = new HumanRace();
                    break;
                case 1:
                    playerRace = new ElvenRace();
                    break;
                case 2:
                    playerRace = new DwarvenRace();
                    break;
                case 3:
                    playerRace = new GoblinRace();
                    break;
                case 4:
                    playerRace = new GiantRace();
                    break;
            }
            GameObject.Find("Player").GetComponent<Player>().generatePlayer(playerRace, playerClass, name, GameObject.Find("dropDifficulty").GetComponent<Dropdown>().value);
        }

        public void switchMap()
        {
            if (state == UIState.MAP)
            {
                closeMap();
            }
            else
            {
                openMap();
            }
        }

        public void switchCharactersheet()
        {
            if (state == UIState.CHARACTER)
            {
                closeCharactersheet();
            }
            else
            {
                openCharactersheet();
            }
        }

        public void openCharacterCreation()
        {
            mainMenu.transform.localScale = new Vector3(0, 0, 0);
            characterCreation.transform.localScale = new Vector3(1, 1, 1);
            state = UIState.CHARACTERCREATION;
        }

        public void closeCharacterCreation()
        {
            characterCreation.transform.localScale = new Vector3(0, 0, 0);
            state = UIState.MAINMENU;
            openMainMenu();
        }

        public void openOptions()
        {
            options.SetActive(true);
            GameObject.Find("AudioHandler").GetComponent<AudioHandler>().setSlider();
            hideOtherElements(options);
            if (state == UIState.MAINMENU)
            {
                state = UIState.OPTIONS;
            }
            else
            {
                state = UIState.PAUSEOPTIONS;
            }
            GameObject.Find("ScrollbarOptions").GetComponent<Scrollbar>().value = 1f;

        }

        public void closeOptions()
        {
            options.SetActive(false);
            if (state == UIState.PAUSEOPTIONS)
            {
                state = UIState.PAUSE;
                openPauseMenu();
            }
            else
            {
                state = UIState.MAINMENU;
                openMainMenu();
            }
        }

        public void openCharactersheet()
        {
            hideOtherElements(charactersheet);
            state = UIState.CHARACTER;
        }

        public void closeCharactersheet()
        {
            charactersheet.transform.localScale = new Vector3(0, 0, 0);
            showHUD();
            state = UIState.GAME;
        }

        public void openMap()
        {
            hideOtherElements(map);
            map.transform.localScale = new Vector3(1, 1, 1);
            state = UIState.MAP;
        }

        public void closeMap()
        {
            map.transform.localScale = new Vector3(0, 0, 0);
            showHUD();
            state = UIState.GAME;
        }

        public void openFight()
        {
            GameObject.Find("txtRounds").GetComponent<Text>().text = "-1";
            hideOtherElements(fight);
            state = UIState.FIGHT;
        }

        public void closeFight()
        {
            fight.transform.localScale = new Vector3(0, 0, 0);
            showHUD();
            state = UIState.GAME;
        }

        public void showHUD()
        {
            playerHUD.transform.localScale = new Vector3(1,1,1);
            compass.transform.localScale = new Vector3(1, 1, 1);
        }

        public void openMainMenu()
        {
            hideOtherElements(mainMenu);
            state = UIState.MAINMENU;
        }

        public void switchPauseMenu()
        {
            if (state == UIState.GAME || state == UIState.CHARACTER || state == UIState.MAP || state == UIState.PAUSE || state == UIState.QUEST)
            {
                if (state == UIState.PAUSE)
                {
                    closePauseMenu();
                }
                else
                {
                    openPauseMenu();
                }
            }
        }

        public void switchQuestLog()
        {
            if (state == UIState.QUEST)
            {
                closeQuestLog();
            }
            else
            {
                openQuestLog();
            }
        }

        public void openQuestLog()
        {
            state = UIState.QUEST;
            hideOtherElements(questlog);
            GameObject.Find("Player").GetComponent<Player>().updateKillcount(GameObject.Find("txtSlimesKilled"));
            GameObject.Find("WorldGenerator").GetComponent<WorldGenerator>().updateCityCount(GameObject.Find("txtCitiesFound"));
        }

        public void closeQuestLog()
        {
            questlog.transform.localScale = new Vector3(0,0,0);
            state = UIState.GAME;
            showHUD();
        }

        public void adaptScreen()
        {
            GameObject resolution = GameObject.Find("dropResolution");
            GameObject mode = GameObject.Find("dropMode");

            switch (resolution.GetComponent<Dropdown>().value)
            {
                case 0:
                    Screen.SetResolution(800,600, Screen.fullScreenMode);
                    break;
                case 1:
                    Screen.SetResolution(1280, 800, Screen.fullScreenMode);
                    break;
                case 2:
                    Screen.SetResolution(1920,1080, Screen.fullScreenMode);
                    break;
            }

            switch (mode.GetComponent<Dropdown>().value)
            {
                case 0:
                    if (Screen.fullScreenMode != FullScreenMode.Windowed)
                    {
                        Screen.fullScreenMode = FullScreenMode.Windowed;
                    }
                    break;
                case 1:
                    if (Screen.fullScreenMode != FullScreenMode.ExclusiveFullScreen)
                    {
                        Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
                    }
                    break;
                case 2:
                    if (Screen.fullScreenMode != FullScreenMode.FullScreenWindow)
                    {
                        Screen.fullScreenMode = FullScreenMode.FullScreenWindow;
                    }
                    break;
            }
        }

        public void openPauseMenu()
        {
            hideOtherElements(pauseMenu);
            state = UIState.PAUSE;
        }

        public void closePauseMenu()
        {
            pauseMenu.transform.localScale = new Vector3(0, 0, 0);
            showHUD();
            state = UIState.GAME;
        }

        public void showDeathScreen()
        {
            state = UIState.DEATH;
            hideOtherElements(deathscreen);
        }

        public void hideOtherElements(GameObject obj)
        {
            for (int i = 0; i < GameObject.Find("Canvas").transform.childCount; i++)
            {
                if (!GameObject.Find("Canvas").transform.GetChild(i).gameObject.Equals(obj))
                {
                    GameObject.Find("Canvas").transform.GetChild(i).localScale = new Vector3(0, 0, 0);
                }
            }
            obj.transform.localScale = new Vector3(1, 1, 1);
        }

        public void displayInformation(string information)
        {
            GameObject.Find("txtObjectName").GetComponent<Text>().text = information;
            this.information.transform.localScale = new Vector3(1, 1, 1);
        }

        public void hideInformation()
        {
            information.transform.localScale = new Vector3(0, 0, 0);
        }

        public void showMessage(string message)
        {
            this.message.GetComponent<LogWriter>().addMessage(message);
        }

        public void updateFightInterface(GameObject enemy, GameObject player)
        {
            updateFightInterfacePlayer(player);
            updateFightInterfaceEnemy(enemy);
            updateFightInterfaceActions(player);
            GameObject.Find("txtRounds").GetComponent<Text>().text = (int.Parse(GameObject.Find("txtRounds").GetComponent<Text>().text) + 1).ToString();
        }

        private void updateFightInterfaceActions(GameObject player)
        {
            GameObject actionFour = GameObject.Find("action4");
            GameObject actionFive = GameObject.Find("action5");
            GameObject actionSix = GameObject.Find("action6");

            player.GetComponent<Player>().displayAction(0, actionFour.transform.Find("imgAction").gameObject, actionFour.transform.Find("descAction").gameObject);
            player.GetComponent<Player>().displayAction(1, actionFive.transform.Find("imgAction").gameObject, actionFive.transform.Find("descAction").gameObject);
            player.GetComponent<Player>().displayAction(2, actionSix.transform.Find("imgAction").gameObject, actionSix.transform.Find("descAction").gameObject);
        }

        private void updateFightInterfacePlayer(GameObject player)
        {
            // { health, maxHealth, secondary, maxSecondary, strength, dexterity, intelligence };
            int[] playerStats = player.GetComponent<Player>().getStats();

            GameObject foreground = GameObject.Find("healthForegroundPlayer");
            GameObject background = GameObject.Find("healthBackgroundPlayer");
            GameObject text = GameObject.Find("healthTextPlayer");
            updateBar(foreground, background, text, playerStats[1], playerStats[0]);

            foreground = GameObject.Find("secondaryForegroundPlayer");
            background = GameObject.Find("secondaryBackgroundPlayer");
            text = GameObject.Find("secondaryTextPlayer");
            updateBar(foreground, background, text, playerStats[3], playerStats[2]);
        }

        private void updateFightInterfaceEnemy(GameObject enemy)
        {
            // { health, maxHealth, secondary, maxSecondary, strength, dexterity, intelligence };
            int[] enemyStats = enemy.GetComponent<Enemy>().getStats();

            GameObject foreground = GameObject.Find("healthForegroundEnemy");
            GameObject background = GameObject.Find("healthBackgroundEnemy");
            GameObject text = GameObject.Find("healthTextEnemy");
            updateBar(foreground, background, text, enemyStats[1], enemyStats[0]);

            foreground = GameObject.Find("secondaryForegroundEnemy");
            background = GameObject.Find("secondaryBackgroundEnemy");
            text = GameObject.Find("secondaryTextEnemy");
            updateBar(foreground, background, text, enemyStats[3], enemyStats[2]);
        }

        public void adjustInformation(Player player)
        {
            // { health, maxHealth, secondary, maxSecondary, strength, dexterity, intelligence, level, experience, maxExperience, points};
            int[] playerStats = player.GetComponent<Player>().getStats();

            GameObject.Find("txtStrength").GetComponent<Text>().text = "STR: " + playerStats[4];
            GameObject.Find("txtDexterity").GetComponent<Text>().text = "DEX: " + playerStats[5];
            GameObject.Find("txtIntelligence").GetComponent<Text>().text = "INT: " + playerStats[6];
            GameObject.Find("txtHealth").GetComponent<Text>().text = "Health: " + playerStats[1];
            GameObject.Find("txtSecondary").GetComponent<Text>().text = "Secondary: " + playerStats[3];

            updateHealthUI(playerStats[0], playerStats[1]);
            updateSecondaryUI(playerStats[2], playerStats[3]);
            updateExperienceUI(playerStats[8], playerStats[9]);

            player.updateName(GameObject.Find("txtName").GetComponent<Text>());
            updatePoints(playerStats[10]);
            player.displaySkills(GameObject.Find("pnlSkills"));
        }

        private void updatePoints(int points)
        {
            GameObject strength = GameObject.Find("btnStrengthIncrease");
            GameObject dexterity = GameObject.Find("btnDexterityIncrease");
            GameObject intelligence = GameObject.Find("btnIntelligenceIncrease");
            GameObject health = GameObject.Find("btnHealthIncrease");
            GameObject secondary = GameObject.Find("btnSecondaryIncrease");
            GameObject txtPoints = GameObject.Find("txtPoints");

            txtPoints.GetComponent<Text>().text = "Your available points: " + points;

            if (points > 0)
            {
                strength.transform.localScale = new Vector3(1, 1, 1);
                dexterity.transform.localScale = new Vector3(1, 1, 1);
                intelligence.transform.localScale = new Vector3(1, 1, 1);
                health.transform.localScale = new Vector3(1, 1, 1);
                secondary.transform.localScale = new Vector3(1, 1, 1);
            }
            else
            {
                strength.transform.localScale = new Vector3(0, 0, 0);
                dexterity.transform.localScale = new Vector3(0, 0, 0);
                intelligence.transform.localScale = new Vector3(0, 0, 0);
                health.transform.localScale = new Vector3(0, 0, 0);
                secondary.transform.localScale = new Vector3(0, 0, 0);
            }
        }

        private void updateHealthUI(int health, int maxHealth)
        {
            GameObject foreground = GameObject.Find("healthForegroundInformation");
            GameObject background = GameObject.Find("healthBackgroundInformation");
            GameObject text = GameObject.Find("healthTextInformation");

            updateBar(foreground, background, text, maxHealth, health);
        }

        private void updateSecondaryUI(int secondary, int maxSecondary)
        {
            GameObject foreground = GameObject.Find("secondaryForegroundInformation");
            GameObject background = GameObject.Find("secondaryBackgroundInformation");
            GameObject text = GameObject.Find("secondaryTextInformation");

            updateBar(foreground, background, text, maxSecondary, secondary);
        }

        private void updateExperienceUI(int experience, int maxExperience)
        {
            GameObject foreground = GameObject.Find("experienceForeground");
            GameObject background = GameObject.Find("experienceBackground");
            GameObject text = GameObject.Find("experienceText");

            updateBar(foreground, background, text, maxExperience, experience);
        }

        public void updateHUD(Player player)
        {
            // { health, maxHealth, secondary, maxSecondary, strength, dexterity, intelligence, level, experience, maxExperience};
            int[] playerStats = player.GetComponent<Player>().getStats();

            GameObject information = GameObject.Find("txtInformationHUD");
            player.updateNameHUD(information.GetComponent<Text>());

            GameObject foreground = GameObject.Find("healthForegroundHUD");
            GameObject background = GameObject.Find("healthBackgroundHUD");
            updateBar(foreground, background, null, playerStats[1], playerStats[0]);

            foreground = GameObject.Find("secondaryForegroundHUD");
            background = GameObject.Find("secondaryBackgroundHUD");
            updateBar(foreground, background, null, playerStats[3], playerStats[2]);
        }

        public void updateBar(GameObject bar, GameObject barBackground, GameObject textField, int maxValue, int minValue)
        {
            string text = minValue + "/" + maxValue;
            double percentage = (1 / (double)maxValue) * minValue;
            float change = (float)(barBackground.GetComponent<RectTransform>().rect.width - (barBackground.GetComponent<RectTransform>().rect.width * percentage));

            if (textField != null)
            {
                textField.GetComponent<Text>().text = text;
            }
            bar.GetComponent<RectTransform>().offsetMax = new Vector2(-change, bar.GetComponent<RectTransform>().offsetMax.y);
        }

        public void openTutorial()
        {
            hideOtherElements(tutorial);
            state = UIState.TUTORIAL;
        }
    }
}