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

namespace mgaia.Utils
{
    public class PoolMenuFabric : IMenuFabric
    {
        private Dictionary<Type, string> mPaths = new Dictionary<Type, string>();

        /// <summary>
        /// Registra o caminho do prefab para o menu do tipo enviado
        /// </summary>
        public void RegisterPrefabForMenu<T>(string path, bool createPool = true) where T : BaseMenuBehaviour
        {
            Type menuType = typeof(T);

            Assert.AssertTrue(!mPaths.ContainsKey(menuType), "Já existe um caminho registrado para o menu de tipo " + menuType.Name);

            if (createPool)
            {
                PoolManager.Instance.CreatePool(path, 1);
            }

            mPaths.Add(menuType, path);
        } 

        /// <summary>
        /// Cria um menu a partir da Pool
        /// </summary>
        public T Create<T>() where T : BaseMenuBehaviour
        {
            Type menuType = typeof(T);

            Assert.AssertTrue(mPaths.ContainsKey(menuType), "Não existe um caminho registrado para o menu de tipo " + menuType.Name);

            PoolElement poolElement = PoolManager.Instance.Pop<PoolElement>(mPaths[menuType]);
            poolElement.PoolElementActionFinished += poolElement_PoolElementActionFinished;

            T menuBehaviour = poolElement.GetComponent<T>();

            Assert.AssertTrue(menuBehaviour != null, "Não existe um behaviour " + menuType.Name + " cadastrado no prefab!");

            return menuBehaviour;
        }

        /// <summary>
        /// Evento disparado quando um elemento é removido da pool, remove o menu do dicionário de referências
        /// </summary>
        private void poolElement_PoolElementActionFinished(PoolElement element)
        {
            BaseMenuBehaviour menuBehaviour = element.GetComponent<BaseMenuBehaviour>();

            Assert.AssertTrue(menuBehaviour != null, "Não existe um BaseMenuBehaviour no menu sendo removido!");

            element.PoolElementActionFinished -= poolElement_PoolElementActionFinished;
        }

        /// <summary>
        /// Remove um menu
        /// </summary>
        public void Destroy(BaseMenuBehaviour menu)
        {
            PoolElement poolElement = menu.GetComponent<PoolElement>();

            Assert.AssertTrue(poolElement != null, "Não existe um PoolElement no menu de nome " + menu.GetType().Name);

            poolElement.OnPoolElementActionFinished();
        }
    }
}