using System;
using System.Linq;
using System.Threading;
namespace OpenNest.Engine.Jobs.Remote;
///
/// Answers each solve with the next recorded result of a ,
/// after checking it is asked the same job the recording engine was. A different question
/// (the drawings no longer bundle or recover the same way) or one too many fails the replay
/// with ; nothing is ever solved here.
///
internal sealed class ReplayNestingEngine : INestingEngine
{
private readonly NestSolveTranscript transcript;
private int next;
public ReplayNestingEngine(NestSolveTranscript transcript)
{
this.transcript = transcript ?? throw new ArgumentNullException(nameof(transcript));
}
/// True once every recorded solve has been replayed.
public bool Finished => next == transcript.Solves.Count;
public NestJobResult Solve(NestJob job, IProgress progress = null, CancellationToken token = default)
{
ArgumentNullException.ThrowIfNull(job);
token.ThrowIfCancellationRequested();
if (next >= transcript.Solves.Count)
throw new NestReplayMismatchException("The nest needed more engine runs here than it did on the server.");
var solve = transcript.Solves[next++];
if (solve.Request == null
|| !solve.Request.SequenceEqual(NestSolveTranscript.Fingerprint(job), StringComparer.Ordinal))
throw new NestReplayMismatchException("The nest asked the engine a different question here than it did on the server.");
return solve.Result.ToResult(job);
}
}
/// The server's result cannot be replayed against the drawings and stock here.
public sealed class NestReplayMismatchException : InvalidOperationException
{
public NestReplayMismatchException(string message) : base(message) { }
}