// ---------------------------------------------------------------------------
// BT.Framework
// ObservableQueue.cs — 변경 이벤트를 내장한 Queue<T>
// ---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;

namespace BurningTimes.Core.Container
{
    /// <summary>
    /// Enqueue/Dequeue/Reset 이벤트를 인스턴스 단위로 발행하는 FIFO 큐.
    /// </summary>
    /// <remarks>
    /// 설계 문서 §3-2. 기존 <c>UniQueue</c>·<c>UniEventQueue</c>·<c>UniObserverQueue</c> 3종 통합 대체.
    /// </remarks>
    public class ObservableQueue<T> : IReadOnlyCollection<T>
    {
        private readonly Queue<T> _items;

        public event Action<T> Enqueued;
        public event Action<T> Dequeued;
        public event Action Reset;

        public ObservableQueue() { _items = new Queue<T>(); }
        public ObservableQueue(int capacity) { _items = new Queue<T>(capacity); }

        public int Count => _items.Count;

        public void Enqueue(T item)
        {
            _items.Enqueue(item);
            Enqueued?.Invoke(item);
        }

        public T Dequeue()
        {
            T item = _items.Dequeue();
            Dequeued?.Invoke(item);
            return item;
        }

        public bool TryDequeue(out T item)
        {
            if (_items.Count == 0) { item = default; return false; }
            item = _items.Dequeue();
            Dequeued?.Invoke(item);
            return true;
        }

        public T Peek() => _items.Peek();
        public bool TryPeek(out T item)
        {
            if (_items.Count == 0) { item = default; return false; }
            item = _items.Peek();
            return true;
        }

        public void Clear()
        {
            if (_items.Count == 0) return;
            _items.Clear();
            Reset?.Invoke();
        }

        public bool Contains(T item) => _items.Contains(item);

        public Queue<T>.Enumerator GetEnumerator() => _items.GetEnumerator();
        IEnumerator<T> IEnumerable<T>.GetEnumerator() => _items.GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();
    }
}
