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


/// <summary>
/// Helper class to call event of a specified type of event on all registered object for this specific event.
/// </summary>
public static class ExecuteEvents
{
    private static readonly Dictionary<Type, List<IEventSystemHandler>> s_eventHandlers = new Dictionary<Type, List<IEventSystemHandler>>();

    public static int Count<TEventSystemHandler>() where TEventSystemHandler : IEventSystemHandler
    {
        List<IEventSystemHandler> handlerList;
        if (s_eventHandlers.TryGetValue(typeof(TEventSystemHandler), out handlerList))
        {
            return handlerList.Count;
        }

        return 0;
    }

    public static void AddHandler<TEventSystemHandler>(TEventSystemHandler _handler) where TEventSystemHandler : IEventSystemHandler
    {
        List<IEventSystemHandler> handlerList;
        if (s_eventHandlers.TryGetValue(typeof(TEventSystemHandler), out handlerList) == false)
        {
            s_eventHandlers[typeof(TEventSystemHandler)] = handlerList = new List<IEventSystemHandler>();
        }

        handlerList.Add(_handler);
    }

    public static void RemoveHandler<TEventSystemHandler>(TEventSystemHandler _handler) where TEventSystemHandler : IEventSystemHandler
    {
        List<IEventSystemHandler> handlerList;
        if (s_eventHandlers.TryGetValue(typeof(TEventSystemHandler), out handlerList))
        {
            handlerList.Remove(_handler);
        }
    }

    public static bool Execute<TEventSystemHandler>(BaseEventData _eventData, UnityEngine.EventSystems.ExecuteEvents.EventFunction<TEventSystemHandler> _functor) where TEventSystemHandler : IEventSystemHandler
    {
        List<IEventSystemHandler> handlerList;
        if (s_eventHandlers.TryGetValue(typeof(TEventSystemHandler), out handlerList))
        {
            for (int index = 0; index < handlerList.Count; ++index)
            {
                TEventSystemHandler handler;
                try
                {
                    handler = (TEventSystemHandler)handlerList[index];
                }
                catch (Exception ex)
                {
                    Debug.LogException(new Exception(string.Format("Type {0} expected {1} received.", typeof(TEventSystemHandler).Name, handlerList[index].GetType().Name), ex));
                    continue;
                }

                try
                {
                    _functor(handler, _eventData);
                }
                catch (Exception ex)
                {
                    Debug.LogException(ex);
                }
            }

            return handlerList.Count > 0;
        }

        return false;
    }
}
