using System;
using System.Collections;
using System.Collections.Generic;
using MotionFramework.Console;
using MotionFramework.Reference;
namespace MotionFramework.Event
{
	/// 
	/// 事件管理器
	/// 
	public sealed class EventManager : ModuleSingleton, IModule
	{
		private class PostWrapper : IReference
		{
			public int PostFrame;
			public int EventID;
			public IEventMessage Message;
			public void OnRelease()
			{
				PostFrame = 0;
				EventID = 0;
				Message = null;
			}
		}
		private readonly Dictionary>> _listeners = new Dictionary>>(1000);
		private readonly List _postWrappers = new List(1000);
		void IModule.OnCreate(System.Object param)
		{
		}
		void IModule.OnUpdate()
		{
			for (int i = _postWrappers.Count - 1; i >= 0; i--)
			{
				var wrapper = _postWrappers[i];
				if (UnityEngine.Time.frameCount > wrapper.PostFrame)
				{
					SendMessage(wrapper.EventID, wrapper.Message);
					_postWrappers.RemoveAt(i);
					ReferencePool.Release(wrapper);
				}
			}
		}
		void IModule.OnDestroy()
		{
			DestroySingleton();
		}
		void IModule.OnGUI()
		{
			ConsoleGUI.Lable($"[{nameof(EventManager)}] Listener total count : {GetAllListenerCount()}");
		}
		/// 
		/// 添加监听
		/// 
		public void AddListener(System.Action listener) where TEvent : IEventMessage
		{
			AddListener(typeof(TEvent), listener);
		}
		/// 
		/// 添加监听
		/// 
		public void AddListener(System.Type eventType, System.Action listener)
		{
			int eventId = eventType.GetHashCode();
			AddListener(eventId, listener);
		}
		/// 
		/// 添加监听
		/// 
		public void AddListener(int eventId, System.Action listener)
		{
			if (_listeners.ContainsKey(eventId) == false)
				_listeners.Add(eventId, new LinkedList>());
			if (_listeners[eventId].Contains(listener) == false)
				_listeners[eventId].AddLast(listener);
		}
		/// 
		/// 移除监听
		/// 
		public void RemoveListener(System.Action listener) where TEvent : IEventMessage
		{
			RemoveListener(typeof(TEvent), listener);
		}
		/// 
		/// 移除监听
		/// 
		public void RemoveListener(System.Type eventType, System.Action listener)
		{
			int eventId = eventType.GetHashCode();
			RemoveListener(eventId, listener);
		}
		/// 
		/// 移除监听
		/// 
		public void RemoveListener(int eventId, System.Action listener)
		{
			if (_listeners.ContainsKey(eventId))
			{
				if (_listeners[eventId].Contains(listener))
					_listeners[eventId].Remove(listener);
			}
		}
		/// 
		/// 实时广播事件
		/// 
		public void SendMessage(IEventMessage message)
		{
			int eventId = message.GetType().GetHashCode();
			SendMessage(eventId, message);
		}
		/// 
		/// 实时广播事件
		/// 
		public void SendMessage(int eventId, IEventMessage message)
		{
			if (_listeners.ContainsKey(eventId) == false)
				return;
			LinkedList> listeners = _listeners[eventId];
			if (listeners.Count > 0)
			{
				var currentNode = listeners.Last;
				while (currentNode != null)
				{
					currentNode.Value.Invoke(message);
					currentNode = currentNode.Previous;
				}
			}
			// 回收引用对象
			IReference refClass = message as IReference;
			if (refClass != null)
				ReferencePool.Release(refClass);
		}
		/// 
		/// 延迟广播事件
		/// 
		public void PostMessage(IEventMessage message)
		{
			int eventId = message.GetType().GetHashCode();
			PostMessage(eventId, message);
		}
		/// 
		/// 延迟广播事件
		/// 
		public void PostMessage(int eventId, IEventMessage message)
		{
			var wrapper = ReferencePool.Spawn();
			wrapper.PostFrame = UnityEngine.Time.frameCount;
			wrapper.EventID = eventId;
			wrapper.Message = message;
			_postWrappers.Add(wrapper);
		}
		/// 
		/// 清空所有监听
		/// 
		public void ClearListeners()
		{
			foreach (int eventId in _listeners.Keys)
			{
				_listeners[eventId].Clear();
			}
			_listeners.Clear();
		}
		/// 
		/// 获取监听者总数
		/// 
		private int GetAllListenerCount()
		{
			int count = 0;
			foreach (var list in _listeners)
			{
				count += list.Value.Count;
			}
			return count;
		}
	}
}