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

/* https://learn.unity.com/tutorial/create-a-simple-messaging-system-with-events */
public class EventManager<T, V> : MonoBehaviour
    where V : UnityEvent //where V : UnityEvent<int>
{

    private Dictionary<T, V> eventDictionary;

    private static EventManager<T, V> eventManager;

    public static EventManager<T, V> instance
    {
        get
        {
            if (!eventManager)
            {
                eventManager = FindObjectOfType(typeof(EventManager<T, V>)) as EventManager<T, V>;

                if (!eventManager)
                {
                    Debug.LogError("There needs to be one active EventManger script on a GameObject in your scene.");
                }
                else
                {
                    eventManager.Init();
                }
            }

            return eventManager;
        }
    }

    void Init()
    {
        if (eventDictionary == null)
        {
            eventDictionary = new Dictionary<T, V>();
        }
    }

    public static void StartListening(T eventName, UnityAction listener)
    {
        V thisEvent = null;

        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.AddListener(listener);
        }
        else
        {
            thisEvent = (V)(new UnityEvent());

            thisEvent.AddListener(listener);

            instance.eventDictionary.Add(eventName, thisEvent);
        }
    }

    public static void StopListening(T eventName, UnityAction listener)
    {
        if (eventManager == null) return;

        V thisEvent = null;

        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.RemoveListener(listener);
        }
    }

    public static void TriggerEvent(T eventName)
    {
        V thisEvent = null;

        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.Invoke();
        }
    }
}