/**
 * Source-space undo/redo history for the chat-form contenteditable, whose
 * imperative DOM rebuilds destroy the browser's native undo stack.
 * Entries record the state BEFORE an edit; edits within `groupWindowMs`
 * extend the open group so a typing burst undoes as a unit, while
 * structural edits (paste, mention insert, clear) pass `newGroup`.
 */

export interface SourceHistoryEntry {
	value: string;
	caret: number;
}

export class SourceHistory {
	private undoStack: SourceHistoryEntry[] = [];
	private redoStack: SourceHistoryEntry[] = [];
	private lastPush = 0;

	constructor(
		private limit = 100,
		private groupWindowMs = 800
	) {}

	push(entry: SourceHistoryEntry, now: number, newGroup = false): void {
		if (newGroup || now - this.lastPush >= this.groupWindowMs || this.undoStack.length === 0) {
			this.undoStack.push(entry);

			if (this.undoStack.length > this.limit) this.undoStack.shift();
		}

		this.lastPush = now;
		this.redoStack = [];
	}

	undo(current: SourceHistoryEntry): SourceHistoryEntry | null {
		const entry = this.undoStack.pop();

		if (!entry) return null;

		this.redoStack.push(current);
		this.lastPush = 0; // the next edit after an undo starts a new group

		return entry;
	}

	redo(current: SourceHistoryEntry): SourceHistoryEntry | null {
		const entry = this.redoStack.pop();

		if (!entry) return null;

		this.undoStack.push(current);
		this.lastPush = 0;

		return entry;
	}
}
