import { Signal, InjectionToken, Provider } from '@angular/core';

type DeepPartial<T> = {
    [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};

declare function deepDelete<T>(target: T, patch: DeepPartial<T>): T;

declare function deepMerge<T>(target: T, patch: DeepPartial<T>): T;

interface IMutatorChange {
    version: number;
    notifier: string | null;
}

interface Changes<T> {
    value: DeepPartial<T>;
    action: 'create' | 'update' | 'delete';
}
declare abstract class Mutator<T extends object> {
    private _base;
    private readonly _undoStack;
    private readonly _redoStack;
    private readonly _config;
    private readonly _limit;
    private readonly _change;
    private readonly _canUndo;
    private readonly _canRedo;
    get changes(): Signal<IMutatorChange>;
    get canUndo(): Signal<boolean>;
    get canRedo(): Signal<boolean>;
    get base(): T;
    initialize(value: T): void;
    create(patch: DeepPartial<T>, notifier?: string): void;
    update(patch: DeepPartial<T>, notifier?: string): void;
    delete(patch: DeepPartial<T>, notifier?: string): void;
    _addChanges(changes: Changes<T>, notifier: string | null): void;
    private _setChangeObject;
    getSnapshot(): T;
    private _applyChange;
    undo(): void;
    redo(): void;
    patchBase(patch: DeepPartial<T>): void;
    deleteFromBase(patch: DeepPartial<T>): void;
    private _updateSignals;
}

interface MutatorConfig {
    limit?: number;
}
declare const MUTATOR_CONFIG: InjectionToken<MutatorConfig>;
declare function provideMutator(config?: MutatorConfig): Provider[];

export { MUTATOR_CONFIG, Mutator, deepDelete, deepMerge, provideMutator };
export type { DeepPartial, IMutatorChange, MutatorConfig };
