using DragonISO.Engine.Pipeline;

namespace DragonISO.Engine.Tests.Fakes;

/// <summary>
/// Manual-tick clock. Tests advance the clock and trigger the awaiter explicitly.
/// </summary>
public sealed class FakeFrameClock : IFrameClock
{
    private long _nowTicks;
    private TaskCompletionSource<bool>? _pendingTick;
    private readonly object _gate = new();

    public long NowTicks => Interlocked.Read(ref _nowTicks);

    public void Advance(TimeSpan by)
    {
        Interlocked.Add(ref _nowTicks, by.Ticks);
        TaskCompletionSource<bool>? toSignal;
        lock (_gate)
        {
            toSignal = _pendingTick;
            _pendingTick = null;
        }
        toSignal?.TrySetResult(true);
    }

    public ValueTask<bool> WaitForNextTickAsync(CancellationToken cancellationToken)
    {
        TaskCompletionSource<bool> tcs;
        lock (_gate)
        {
            _pendingTick ??= new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            tcs = _pendingTick;
        }
        cancellationToken.Register(() => tcs.TrySetResult(false));
        return new ValueTask<bool>(tcs.Task);
    }
}
