

namespace Guru
{
    using System;
    using System.Collections.Generic;
    
    /// <summary>
    /// 事件管线基类
    /// </summary>
    public class EventBus
    {

        private Dictionary<string, HashSet<Delegate>> _eventDict;
        protected Dictionary<string, HashSet<Delegate>> EventDict
        {
            get
            {
                if (_eventDict == null)
                {
                    _eventDict = new Dictionary<string, HashSet<Delegate>>(20);
                }
                return _eventDict;
            }
        }

        /// <summary>
        /// 发送事件
        /// </summary>
        /// <param name="eventBody"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public bool Send<T>(T eventBody) where T : struct
        {
            return Trigger<T>(eventBody);
        }


        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="onReceiveMessage"></param>
        /// <typeparam name="T"></typeparam>
        public void Subscribe<T>(Action<T> onReceiveMessage) where T : struct
        {
            AddListener(onReceiveMessage);
        }
        
        public void Unsubscribe<T>(Action<T> onReceiveMessage) where T : struct
        {
            RemoveListener(onReceiveMessage);
        }
        
        public void Dispose()
        {
            if (_eventDict != null)
            {
                foreach (var actions in _eventDict.Values)
                {
                    actions.Clear();
                }
                _eventDict.Clear();
            }
        }

        protected bool HasEvent<T>() where T : struct
        {
            return EventDict.ContainsKey(nameof(T));
        }
        
        
        protected void AddListener<T>(Action<T> onReceiveMessage) where T : struct
        {
            if (!HasEvent<T>())
            {
                EventDict[nameof(T)] = new HashSet<Delegate>();
            }

            EventDict[nameof(T)].Add(onReceiveMessage);
        }
        
        protected void RemoveListener<T>(Action<T> onReceiveMessage) where T : struct
        {
            if (HasEvent<T>())
            {
                if (EventDict[nameof(T)].Contains(onReceiveMessage))
                {
                    EventDict[nameof(T)].Remove(onReceiveMessage);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        protected bool Trigger<T>(T message) where T : struct
        {
            if (HasEvent<T>())
            {
                HashSet<Delegate> newActions = new HashSet<Delegate>(EventDict[nameof(T)].Count);
                foreach (var d in EventDict[nameof(T)])
                {
                    if (d.Target != null)
                    {
                        (d as Action<T>)?.Invoke(message);
                        newActions.Add(d);
                    }
                }

                EventDict[nameof(T)] = newActions; // 过滤掉不存在的时间
                return true;
            }

            return false;
        }


    }
}