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

public static class EventBus 
{

    private static readonly Dictionary<Type, object> _eventHandlers = new Dictionary<Type, object>();
    private static readonly object _lock = new object();

    public static void Register<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
    {
        lock (_lock)
        {
            Type eventType = typeof(TEvent);
            if (!_eventHandlers.ContainsKey(eventType))
            {
                _eventHandlers[eventType] = new List<IEventHandler<TEvent>>();
            }

            var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
            if (handler != null && !handlers.Contains(handler))
            {
                handlers.Add(handler);
            }
        }
    }

    public static void Unregister<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
    {
        lock (_lock)
        {
            Type eventType = typeof(TEvent);
            if (_eventHandlers.ContainsKey(eventType))
            {
                var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
                handlers?.Remove(handler);

                if (handlers != null && handlers.Count == 0)
                {
                    _eventHandlers.Remove(eventType);
                }
            }
        }
    }

    public static void Publish<TEvent>(TEvent eventData) where TEvent : IEvent
    {
        List<IEventHandler<TEvent>> handlersToInvoke = null;

        lock (_lock)
        {
            Type eventType = typeof(TEvent);
            if (_eventHandlers.ContainsKey(eventType))
            {
                var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
                if (handlers != null && handlers.Count > 0)
                {
                    handlersToInvoke = new List<IEventHandler<TEvent>>(handlers);
                }
            }
        }

        // 在锁外执行事件处理，避免死锁
        if (handlersToInvoke != null)
        {
            foreach (var handler in handlersToInvoke)
            {
                try
                {
                    handler?.HandleEvent(eventData);
                }
                catch (Exception e)
                {
                    Debug.LogError($"Event handling error in {handler.GetType().Name}: {e}");
                }
            }
        }
    }

    public static void Clear()
    {
        lock (_lock)
        {
            _eventHandlers.Clear();
        }
    }
}
