// ---------------------------------------------------------------------------
// BT.Framework
// RawEventBus.cs — 문자열 키 기반 이벤트 버스 (특수 용도)
// ---------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using BurningTimes.Core.Util.Log;

namespace BurningTimes.Core.Event.Raw
{
    /// <summary>
    /// 문자열 키 기반 이벤트 버스. 외부 스크립팅·에디터 훅 등 타입 안전 경로가 불가능한 특수 용도에만 사용한다.
    /// </summary>
    /// <remarks>
    /// <para>설계 문서 §3-1 단서. 일반 용도는 <see cref="BurningTimes.Core.Event.EventBus"/> 를 쓴다.</para>
    /// <para>박싱 비용이 발생하므로 hot-path 에서는 피한다.</para>
    /// </remarks>
    public static class RawEventBus
    {
        private static readonly Dictionary<string, List<Action<object>>> HandlersByKey
            = new Dictionary<string, List<Action<object>>>(StringComparer.Ordinal);

        /// <summary>키에 대한 핸들러 등록.</summary>
        public static void Subscribe(string key, Action<object> handler)
        {
            if (string.IsNullOrEmpty(key)) throw new ArgumentException("key empty", nameof(key));
            if (handler == null) throw new ArgumentNullException(nameof(handler));
            if (!HandlersByKey.TryGetValue(key, out var list))
            {
                list = new List<Action<object>>(2);
                HandlersByKey.Add(key, list);
            }
            list.Add(handler);
        }

        /// <summary>키에 대한 핸들러 해제.</summary>
        public static bool Unsubscribe(string key, Action<object> handler)
        {
            if (handler == null) return false;
            return HandlersByKey.TryGetValue(key, out var list) && list.Remove(handler);
        }

        /// <summary>키에 대한 이벤트 발행.</summary>
        public static void Publish(string key, object payload)
        {
            if (!HandlersByKey.TryGetValue(key, out var list)) return;
            int count = list.Count;
            if (count == 0) return;

            var snapshot = new Action<object>[count];
            for (int i = 0; i < count; i++) snapshot[i] = list[i];

            for (int i = 0; i < count; i++)
            {
                try { snapshot[i].Invoke(payload); }
                catch (Exception ex) { Log.Error("RawEventBus", $"핸들러 예외 (key={key})", ex); }
            }
        }

        /// <summary>특정 키 구독자 일괄 제거.</summary>
        public static void Clear(string key)
        {
            if (HandlersByKey.TryGetValue(key, out var list)) list.Clear();
        }

        /// <summary>모든 키 구독자 일괄 제거.</summary>
        public static void ClearAll()
        {
            foreach (var kv in HandlersByKey) kv.Value.Clear();
            HandlersByKey.Clear();
        }

        /// <summary>특정 키의 현재 구독자 수.</summary>
        public static int SubscriberCount(string key)
            => HandlersByKey.TryGetValue(key, out var list) ? list.Count : 0;
    }
}
