import type { DomainError, Encounter } from "./types.js"; export interface UndoRedoState { readonly undoStack: readonly Encounter[]; readonly redoStack: readonly Encounter[]; } const MAX_UNDO_STACK = 50; export const EMPTY_UNDO_REDO_STATE: UndoRedoState = { undoStack: [], redoStack: [], }; export function pushUndo( state: UndoRedoState, snapshot: Encounter, ): UndoRedoState { const newStack = [...state.undoStack, snapshot]; if (newStack.length > MAX_UNDO_STACK) { newStack.shift(); } return { undoStack: newStack, redoStack: [] }; } export function undo( state: UndoRedoState, currentEncounter: Encounter, ): { state: UndoRedoState; encounter: Encounter } | DomainError { if (state.undoStack.length === 0) { return { kind: "domain-error", code: "nothing-to-undo", message: "Nothing to undo", }; } const restored = state.undoStack.at(-1) as Encounter; return { state: { undoStack: state.undoStack.slice(0, -1), redoStack: [...state.redoStack, currentEncounter], }, encounter: restored, }; } export function redo( state: UndoRedoState, currentEncounter: Encounter, ): { state: UndoRedoState; encounter: Encounter } | DomainError { if (state.redoStack.length === 0) { return { kind: "domain-error", code: "nothing-to-redo", message: "Nothing to redo", }; } const restored = state.redoStack.at(-1) as Encounter; return { state: { undoStack: [...state.undoStack, currentEncounter], redoStack: state.redoStack.slice(0, -1), }, encounter: restored, }; } export function clearHistory(): UndoRedoState { return EMPTY_UNDO_REDO_STATE; }