using System;
using System.Collections.Generic;

namespace WS
{
    [ObjectSystem]
    public class EventComponentAwakeSystem : AwakeSystem<EventComponent>
    {
        public override void Awake(EventComponent self)
        {
            EventComponent.Instance = self;
        }
    }

    ///<summary>全局事件</summary>
    public class EventComponent : WSComponent
    {
        public static EventComponent Instance;

        ///<summary>事件代理</summary>
        private class Registerations<T> : WSComponent
        {
            /// <summary>委托可以一对多注册</summary>
            public Action<T> OnReceives = obj => { };

            public override void Dispose()
            {
                base.Dispose();
                OnReceives = null;
            }
        }

        /// <summary>Type事件类型容器</summary>
        private Dictionary<Type, WSComponent> TypeEventDict = new Dictionary<Type, WSComponent>();

        /// <summary>Enum事件类型容器</summary>
        private Dictionary<string, List<Action<Variable[]>>> EnumEventDic = new Dictionary<string, List<Action<Variable[]>>>();

        /// <summary>添加事件监听</summary>
        public void AddEvent<T>(Action<T> onReceive)
        {
            var type = typeof(T);
            WSComponent registerations = null;
            if (TypeEventDict.TryGetValue(type, out registerations))
            {
                var reg = (Registerations<T>)registerations;
                reg.OnReceives += onReceive;
            }
            else
            {
                var reg = new Registerations<T>();
                reg.OnReceives += onReceive;
                TypeEventDict.Add(type, reg);
            }
        }

        ///<summary>添加事件监听</summary>
        public void AddEvent(string eventType, Action<Variable[]> action)
        {
            if (!EnumEventDic.ContainsKey(eventType))
            {
                List<Action<Variable[]>> actions = new List<Action<Variable[]>>();
                actions.Add(action);
                EnumEventDic.Add(eventType, actions);
            }
            else
            {
                List<Action<Variable[]>> actions = EnumEventDic[eventType];
                if (!actions.Contains(action))
                {
                    actions.Add(action);
                    EnumEventDic[eventType] = actions;
                }
            }
        }

        ///<summary>移除事件监听</summary>
        public void RemoveEvent(string eventType, Action<Variable[]> action)
        {
            if (EnumEventDic.ContainsKey(eventType))
            {
                if (EnumEventDic[eventType].Contains(action))
                {
                    EnumEventDic[eventType].Remove(action);
                    if (EnumEventDic[eventType].Count == 0)
                    {
                        EnumEventDic.Remove(eventType);
                    }
                }
            }
        }

        /// <summary>移除事件监听</summary>
        public void RemoveEvent<T>(Action<T> onReceive)
        {
            var type = typeof(T);
            WSComponent registerations = null;
            if (TypeEventDict.TryGetValue(type, out registerations))
            {
                var reg = (Registerations<T>)registerations;
                reg.OnReceives -= onReceive;//将该方法从委托中移除
            }
        }

        /// <summary>发送事件</summary>
        public void SendEvent<T>() where T : new()
        {
            try
            {
                var type = typeof(T);
                WSComponent registerations = null;
                if (TypeEventDict.TryGetValue(type, out registerations))
                {
                    var reg = (Registerations<T>)registerations;
                    reg.OnReceives(new T());//执行委托
                }
            }
            catch (Exception e)
            {
                Log.LogError(e);
            }
        }

        /// <summary>发送事件</summary>
        public void SendEvent<T>(T t)
        {
            try
            {
                var type = typeof(T);
                WSComponent registerations = null;
                if (TypeEventDict.TryGetValue(type, out registerations))
                {
                    var reg = (Registerations<T>)registerations;
                    reg.OnReceives(t);
                }
            }
            catch (Exception e)
            {
                Log.LogError(e);
            }
        }

        ///<summary>派发事件</summary>
        public void SendEvent(string eventType, params Variable[] args)
        {
            try
            {
                if (EnumEventDic.ContainsKey(eventType))
                {
                    List<Action<Variable[]>> actions = EnumEventDic[eventType];
                    for (int i = 0; i < actions.Count; i++)
                    {
                        actions[i].Invoke(args);
                    }
                }
            }
            catch (Exception e)
            {
                Log.LogError(e);
            }
        }

        /// <summary>清空事件</summary>
        public void RemoveAllListener()
        {
            if (EnumEventDic.Count != 0)
            {
                EnumEventDic.Clear();
            }

            foreach (var keyValue in TypeEventDict)
            {
                keyValue.Value.Dispose();
            }
            TypeEventDict.Clear();
        }

        public override void Dispose()
        {
            base.Dispose();
            RemoveAllListener();
        }
    }
}