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

namespace mgaia.Utils
{
    /// <summary>
    /// Classe singleton que gerencia a apresentação e carregamento dos menus
    /// </summary>
    /// <owner>Victor</owner>
    public static class MenuManager
    {
        private static IMenuFabric _sMenuFabric;
        private static List<BaseMenuBehaviour> mMenusInstances = new List<BaseMenuBehaviour>();
        private static bool mObjectCreated = false;

        static MenuManager()
        {
            Create();
        }

        /// <summary>
        /// Ativa o menu manager
        /// </summary>
        public static void Create()
        {
            if (!mObjectCreated)
            {
                GameObject menuManagerObject = new GameObject(Constants.MENU_MANAGER_OBJECT_NAME, typeof(MenuManagerBehaviour));
                menuManagerObject.isStatic = true;
                GameObject.DontDestroyOnLoad(menuManagerObject);
            }
        }

        /// <summary>
        /// Fábrica utilizada para abrir e fechar menus
        /// </summary>
        public static IMenuFabric MenuFabric
        {
            get
            {
                Assert.AssertTrue(_sMenuFabric != null, "Não já nenhuma fábrica de menus setada!");

                return _sMenuFabric;
            }
            set
            {
                Assert.AssertTrue(_sMenuFabric == null, "Já existe uma fábricada de menus setada!");

                _sMenuFabric = value;
            }
        }
        
        /// <summary>
        /// Mostra o menu de tipo enviado
        /// </summary>
        public static T ShowMenu<T>(params object[] parameters) where T : BaseMenuBehaviour
        {
            T menu = MenuFabric.Create<T>();

            mMenusInstances.Add(menu);

            menu.OnShowMenu(parameters);
            
            return menu;
        }

        /// <summary>
        /// Fecha o menu
        /// </summary>
        public static void CloseMenu(BaseMenuBehaviour menu)
        {
            mMenusInstances.Remove(menu);

            menu.OnRemoveMenu();
            MenuFabric.Destroy(menu);
        }

        /// <summary>
        /// Fecha o menu de tipo passado
        /// </summary>
        public static void CloseMenu<T>() where T : BaseMenuBehaviour
        {
            BaseMenuBehaviour firstInstanceOfType = mMenusInstances.First(menu => menu.GetType().Equals(typeof(T)));

            if (firstInstanceOfType != null)
            {
                CloseMenu(firstInstanceOfType);
            }
        }

        /// <summary>
        /// Evento de update
        /// </summary>
        internal static void Update()
        {
            //Evita o problema de chamar um update de um menu criado dentro desse update
            BaseMenuBehaviour[] actualMenusIntances = mMenusInstances.ToArray();

            BaseMenuBehaviour firstModalBehaviour = actualMenusIntances.Where(menu => menu.IsModal).NewOrderBy(menu => menu.Priority).Last();

            if (firstModalBehaviour != null)
            {
                firstModalBehaviour.UpdateRespectingModal();
            }
            else
            {
                actualMenusIntances.ForEach(menu => menu.UpdateRespectingModal());
            }
        }
    }
}