using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace UniversalNetFrame451;

public class EventQueue<T>
{
    public EventQueue(Action<T> queueHandler)
    {
        this._queueHandler = queueHandler;
        this._cancellation = new CancellationToken(false);
        this._queueEvent = new(false);
        this._pauseController = new(true);
        this._queue = new();

        Task.Factory.StartNew(WorkingTask, TaskCreationOptions.LongRunning);
    }


    private readonly Queue<T> _queue;
    private readonly Action<T> _queueHandler;

    private readonly AutoResetEvent _queueEvent;
    private readonly ManualResetEvent _pauseController;

    private CancellationToken _cancellation;

    public int Count
    {
        get
        {
            lock (this._queue)
                return this._queue.Count;
        }
    }

    public void Pause() => this._pauseController.Reset();
    public void Resume() => this._pauseController.Set();
    public void Cancel() => this._cancellation = new(true);

    public bool Enqueue(T input)
    {
        if (this._cancellation.IsCancellationRequested)
            return false;

        lock (_queue)
            this._queue.Enqueue(input);
        this._queueEvent.Set();

        return true;
    }

    private void WorkingTask()
    {
        for (T content; !this._cancellation.IsCancellationRequested; this._pauseController.WaitOne(-1))
        {
            if (this.Count == 0)
            {
                this._queueEvent.Reset();
                this._queueEvent.WaitOne(-1);
            }

            lock (_queue)
                content = this._queue.Dequeue();

            this._queueHandler?.Invoke(content);
        }

        lock (this._queue)
            this._queue.Clear();
    }
}