using IFSEngine.Model;
namespace IFSRenderer.Shared;
/// <summary>
/// Snapshot-based undo/redo. Ported verbatim from the WPF app's helper of the same name.
/// </summary>
/// <remarks>
/// States are whole serialized fractals rather than reversible commands, which is why this
/// goes through <see cref="IfsNodesSerializer"/> - and therefore why undo also restores node
/// graph positions, not just parameters.
/// </remarks>
public class IFSHistoryTracker
{
private Stack<string> UndoStack { get; } = new();
private Stack<string> RedoStack { get; } = new();
public bool IsHistoryUndoable => UndoStack.Count > 0;
public bool IsHistoryRedoable => RedoStack.Count > 0;
public IFS Undo(IFS current, IEnumerable<TransformPlugin> transforms, IEnumerable<EffectPlugin> postfxs)
{
if (!IsHistoryUndoable)
throw new InvalidOperationException();
RedoStack.Push(IfsNodesSerializer.SerializeJsonString(current));
string lastState = UndoStack.Pop();
return IfsNodesSerializer.DeserializeJsonString(lastState, transforms, postfxs, true);
}
public IFS Redo(IFS current, IEnumerable<TransformPlugin> transforms, IEnumerable<EffectPlugin> postfxs)
{
if (!IsHistoryRedoable)
throw new InvalidOperationException();
UndoStack.Push(IfsNodesSerializer.SerializeJsonString(current));
string nextState = RedoStack.Pop();
return IfsNodesSerializer.DeserializeJsonString(nextState, transforms, postfxs, true);
}
public void TakeSnapshot(IFS trackedObject)
{
RedoStack.Clear();
UndoStack.Push(IfsNodesSerializer.SerializeJsonString(trackedObject));
}
public void Clear()
{
UndoStack.Clear();
RedoStack.Clear();
}
}