using System;
using System.Threading;
using System.Threading.Tasks;

namespace PCL.Core.Utils.Threading;

// Partly generated by gpt-5-mini (20250808)
public sealed class AsyncManualResetEvent : IDisposable
{
    private readonly object _syncLock = new();
    private TaskCompletionSource<bool> _tcs = new(TaskCreationOptions.RunContinuationsAsynchronously);
    private readonly ManualResetEventSlim _mre = new(false);
    private bool _disposed;

    public AsyncManualResetEvent(bool initialState = false)
    {
        if (!initialState) return;
        _tcs.SetResult(true);
        _mre.Set();
    }

    /// <summary>
    /// 事件是否已触发。
    /// </summary>
    public bool IsSet
    {
        get { lock (_syncLock) { return _tcs.Task.IsCompleted; } }
    }

    /// <summary>
    /// 异步等待。
    /// </summary>
    /// <param name="cancellationToken">用于结束等待的取消信号</param>
    public Task WaitAsync(CancellationToken cancellationToken = default)
    {
        TaskCompletionSource<bool> t;
        lock (_syncLock) { t = _tcs; }
        if (!cancellationToken.CanBeCanceled || t.Task.IsCompleted) return t.Task;
        return _WaitWithCancellationAsync(t.Task, cancellationToken);
    }

    private static async Task _WaitWithCancellationAsync(Task waitTask, CancellationToken ct)
    {
        var cancelTcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
        using (ct.Register(s => ((TaskCompletionSource<bool>)s!).TrySetResult(true), cancelTcs))
        {
            var completed = await Task.WhenAny(waitTask, cancelTcs.Task).ConfigureAwait(false);
            if (completed == cancelTcs.Task) ct.ThrowIfCancellationRequested();
            await waitTask.ConfigureAwait(false); // propagate exceptions if any
        }
    }

    /// <summary>
    /// 同步等待。
    /// </summary>
    public void Wait() => _mre.Wait();

    /// <summary>
    /// 同步等待，并在超时后结束。
    /// </summary>
    /// <param name="millisecondsTimeout">等待超时的毫秒数</param>
    /// <returns>若已触发事件则为 <c>true</c>，否则为 <c>false</c></returns>
    public bool Wait(int millisecondsTimeout) => _mre.Wait(millisecondsTimeout);

    /// <summary>
    /// 同步等待，并在超时后结束。
    /// </summary>
    /// <param name="timeout">等待超时</param>
    /// <returns>若已触发事件则为 <c>true</c>，否则为 <c>false</c></returns>
    public bool Wait(TimeSpan timeout) => _mre.Wait(timeout);

    /// <summary>
    /// 同步等待，并传递用于结束等待的取消信号。
    /// </summary>
    /// <param name="cancellationToken">用于结束等待的取消信号</param>
    public void Wait(CancellationToken cancellationToken) => _mre.Wait(cancellationToken);

    /// <summary>
    /// 触发事件。
    /// </summary>
    public void Set()
    {
        lock (_syncLock)
        {
            _tcs.TrySetResult(true); // Use TrySetResult to avoid exceptions on repeated Set
            _mre.Set();
        }
    }

    /// <summary>
    /// 重置事件。
    /// </summary>
    public void Reset()
    {
        lock (_syncLock)
        {
            if (!_tcs.Task.IsCompleted) return; // already reset
            _tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            _mre.Reset();
        }
    }

    public void Dispose()
    {
        if (_disposed) return;
        _mre.Dispose();
        _disposed = true;
    }
}
