using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

namespace Event
{
    public delegate void Action<T>(T arg);
    public interface IAction<T> { void OnEvent(T arg); }
    public interface ILocalAction<T> : IAction<T>, IEventSystemHandler { }

    public static class Of<T>
    {
        public static event Action<T> OnGlobalEvent;
        public static void Execute(T arg) { if (OnGlobalEvent != null) OnGlobalEvent(arg); }

        public static void Execute(GameObject obj, T arg)
        {
            ExecuteEvents.Execute<ILocalAction<T>>(obj, null, (e, _) => e.OnEvent(arg));
        }
        public static void ExecuteHierarchy(GameObject obj, T arg)
        {
            ExecuteEvents.ExecuteHierarchy<ILocalAction<T>>(obj, null, (e, _) => e.OnEvent(arg));
        }

        public static void ExecuteAll(GameObject obj, T arg)
        {
            Execute(obj, arg);
            Execute(arg);
        }
        public static void ExecuteHierarchyAll(GameObject obj, T arg)
        {
            ExecuteHierarchy(obj, arg);
            Execute(arg);
        }
    }

    public abstract class GlobalAction<T> : MonoBehaviour, IAction<T>
    {
        public abstract void OnEvent(T arg);
        protected virtual void OnEnable() { Of<T>.OnGlobalEvent += OnEvent; }
        protected virtual void OnDisable() { Of<T>.OnGlobalEvent -= OnEvent; }
    }

    [System.Serializable] public class GameObjectEvent : UnityEvent<GameObject> { }
    [System.Serializable] public class IntEvent : UnityEvent<int> { }
    [System.Serializable] public class FloatEvent : UnityEvent<float> { }
    [System.Serializable] public class StringEvent : UnityEvent<string> { }
}