using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;

    public class BattleUIController : MonoBehaviour
    {
        public static List<Window> openWindows;

        //Transient Windows are windows that will close should a significant event happen
        public static List<Window> transientWindows;

        //A dummy object
        public static Window HighestWindow;

        //Prefab of the back button
        GameObject backButton;

        BattleController BC;

        Window focusedWindow;

        public void initialize(BattleController BaCo)
        {
            BC = BaCo;

            BattleUIController.openWindows = new List<Window>();

            BattleUIController.transientWindows = new List<Window>();

            backButton = Resources.Load<GameObject>("UIElements/uI_BackButton_Panel");

        }

        //Makes it so that only one window is interactable
        public void lockFocus(Window focusedWindow)
        {
            foreach(Window window in openWindows)
            {
                if (window.getAffectedByFocus() && focusedWindow != window)
                {
                    foreach (Button button in window.GetComponentsInChildren<Button>())
                    {
                        button.interactable = false;
                    }
                }
            }
        }

        //Inverse of lock focus
        public void releaseFocus()
        {
            foreach (Window window in openWindows.ToArray())
            {
                foreach (Button button in window.GetComponentsInChildren<Button>())
                {
                    button.interactable = true;
                }
            }
        }

        //This is to just cleanup the lists incase windows get closed
        public void checkForDeleted()
        {
            foreach(Window window in openWindows.ToArray())
            {
                if (window == null)
                {
                    openWindows.Remove(window);
                }
            }
            foreach(Window window in transientWindows.ToArray())
            {
                if(window == null)
                {
                    transientWindows.Remove(window);
                }
            }

        }

        public void closeWindow(Window window)
        {
            lockFocus(window.getParent());
        }


        public BattleUIController()
        {

        }

        public void closeWindow(GameObject item)
        {
            GameObject.Destroy(item);
        }

        public void closeAllTransient()
        {
            foreach(Window window in transientWindows)
            {   //This checks if it's null, please don't be dumb and remove this, you will regret it
                if(window)
                window.closeWindow();
            }
        }

        public GameObject openWindow(string windowName, bool transient = true, string gameObjectName = "Canvas", bool hasBackButton = true)
        {

            GameObject go = GameObject.Instantiate(Resources.Load<GameObject>("UIElements/" + windowName), GameObject.Find(gameObjectName).transform);
            if (transient)
            {   
                BattleUIController.transientWindows.Add(go.GetComponent<Window>());
            }

            openWindows.Add(go.GetComponent<Window>());

            if (hasBackButton)
            {
                GameObject.Instantiate(backButton, go.transform).GetComponentInChildren<BackButtonController>().initialize(this);

            }

            return go;
        }

        public void makeActive(bool toggle)
        {
            checkForDeleted();
            foreach(Window window in openWindows)
            {

                window.enabled = toggle;
            }
        }
    }

    //An abstract class. 
    //Note: this should be abstracted more out. Elements such as "ability" and "attack attempt" are specific
    // to certain implmemetnations. 
    public abstract class Window : MonoBehaviour
    {
        bool affectdByFocus = true;
        List<Window> childrenWindows; 
        Window parentWindow;
        protected BattleCharacterObject character = null;
        protected  AttackAttempt attackAttempt;
        protected Ability ability;

        public Window getParent()
        {
            return parentWindow;
        }

        public bool getAffectedByFocus()
        {
            return affectdByFocus;
        }


        public void initialize(Window parent)
        {
            parentWindow = parent;
            childrenWindows = new List<Window>();
        }

        public void initialize(Window parent, BattleCharacterObject chara)
        {
            parentWindow = parent;
            character = chara;

            childrenWindows = new List<Window>();
        }


        public void initialize(Window parent, AttackAttempt aa)
        {
            attackAttempt = aa;
            parentWindow = parent;

            childrenWindows = new List<Window>();

        }

        public void initialize(Window parent, Ability abilty)
        {
            ability = abilty;
            parentWindow = parent;

            childrenWindows = new List<Window>();

        }

        //It needs to be recursive, because the childen may not necissarily be children in unityland
        public virtual void closeWindow()
        {
            try
            {
                GameObject.Destroy(this.gameObject);
            }catch(MissingReferenceException e)
            {

            }
            if (!(childrenWindows is null))
            {
                if (childrenWindows.Count > 0)
                {
                    foreach (Window child in childrenWindows)
                    {
                        child.closeWindow();
                    }
                }
            }        
        }
    }