import { UndoEvent, UndoStore } from './UndoStore';
/**
 * Interface for managing attached state with undo events.
 */
export interface AttachedStateHandler<TAttachedState = unknown> {
    save(): TAttachedState;
    restore(state: TAttachedState): void;
}
/**
 * Options for creating an UndoManager.
 */
export interface UndoManagerOptions<TAttachedState = unknown> {
    /**
     * The subtree root to track changes on.
     */
    rootNode: object;
    /**
     * Optional UndoStore to use. If not provided, a new one will be created.
     *
     * Note: The UndoStore is not subject to the undo manager, even if it is
     * a child of the rootNode. Changes to the UndoStore itself will not
     * be tracked or undoable.
     */
    store?: UndoStore;
    /**
     * Maximum number of undo levels to keep.
     * @default Infinity
     */
    maxUndoLevels?: number;
    /**
     * Maximum number of redo levels to keep.
     * @default Infinity
     */
    maxRedoLevels?: number;
    /**
     * Attached state management for storing additional state with each undo event.
     */
    attachedState?: AttachedStateHandler<TAttachedState>;
    /**
     * Time window in milliseconds for grouping changes into a single undo event.
     * If undefined (default), changes are only grouped within the same MobX action.
     * If set to a number, changes that occur within this time window will be merged
     * into the last undo event, even if they come from different actions.
     *
     * @default undefined
     */
    groupingDebounceMs?: number;
}
/**
 * Manages undo/redo functionality for a mobx-bonsai node tree.
 * Automatically groups changes that occur within a single MobX action.
 */
export declare class UndoManager<TAttachedState = unknown> {
    #private;
    private disposer;
    private interceptDisposer;
    private isRecordingDisabled;
    private readonly _maxUndoLevels;
    private readonly _maxRedoLevels;
    private readonly attachedState?;
    private readonly groupingDebounceMs?;
    /**
     * Timestamp (performance.now()) of when the last undo event was recorded.
     * Used for grouping debounce logic.
     */
    private lastEventTimestamp;
    /**
     * The root node being tracked.
     */
    readonly rootNode: object;
    /**
     * The UndoStore holding the undo/redo queues.
     */
    readonly store: UndoStore;
    /**
     * Array of changes accumulated during the current action.
     * These will be flushed as a single UndoEvent when the action completes.
     * If length > 0, a flush is already enqueued.
     */
    private pendingChanges;
    /**
     * State saved at the start of the current pending event (before any changes).
     * This is captured lazily when the first change is intercepted.
     * Undefined means it hasn't been captured yet for the current event.
     */
    private attachedStateBeforeNextEvent;
    constructor(options: UndoManagerOptions<TAttachedState>);
    /**
     * Starts tracking changes on the root node.
     */
    private startTracking;
    /**
     * Records a change. If this is the first change in an action, schedules a flush.
     */
    private recordChange;
    /**
     * Schedules a flush to occur when the current action completes.
     */
    private scheduleFlush;
    /**
     * Flushes pending changes as a single UndoEvent.
     */
    private flushPendingChanges;
    /**
     * The undo queue.
     */
    get undoQueue(): ReadonlyArray<UndoEvent>;
    /**
     * The redo queue.
     */
    get redoQueue(): ReadonlyArray<UndoEvent>;
    /**
     * Number of undo steps available.
     */
    get undoLevels(): number;
    /**
     * Whether undo is possible.
     */
    get canUndo(): boolean;
    /**
     * Number of redo steps available.
     */
    get redoLevels(): number;
    /**
     * Whether redo is possible.
     */
    get canRedo(): boolean;
    /**
     * Maximum number of undo levels to keep.
     */
    get maxUndoLevels(): number;
    /**
     * Maximum number of redo levels to keep.
     */
    get maxRedoLevels(): number;
    /**
     * Undoes the last change.
     * @throws if called while inside a MobX action
     * @throws if there are no undo events
     */
    undo(): void;
    /**
     * Redoes the last undone change.
     * @throws if called while inside a MobX action
     * @throws if there are no redo events
     */
    redo(): void;
    /**
     * Clears the undo queue.
     */
    clearUndo: () => void;
    /**
     * Clears the redo queue.
     */
    clearRedo: () => void;
    /**
     * Executes a function without recording changes.
     */
    withoutUndo<T>(fn: () => T): T;
    /**
     * Whether undo recording is currently disabled.
     */
    get isUndoRecordingDisabled(): boolean;
    /**
     * Disposes the undo manager, stopping change tracking.
     */
    dispose(): void;
}
