import { dataTypes } from './constant';
export declare const enum DraftType {
    Object = 0,
    Array = 1,
    Map = 2,
    Set = 3
}
export declare const Operation: {
    readonly Remove: "remove";
    readonly Replace: "replace";
    readonly Add: "add";
};
export declare type DataType = keyof typeof dataTypes;
export declare type PatchesOptions = boolean | {
    /**
     * The default value is `true`. If it's `true`, the path will be an array, otherwise it is a string.
     */
    pathAsArray?: boolean;
    /**
     * The default value is `true`. If it's `true`, the array length will be included in the patches, otherwise no include array length.
     */
    arrayLengthAssignment?: boolean;
};
export interface Finalities {
    draft: ((patches?: Patches, inversePatches?: Patches) => void)[];
    revoke: (() => void)[];
    handledSet: WeakSet<any>;
}
export interface ProxyDraft<T = any> {
    type: DraftType;
    operated?: boolean;
    finalized: boolean;
    original: T;
    copy: T | null;
    proxy: T | null;
    finalities: Finalities;
    options: Options<any, any> & {
        updatedValues?: WeakMap<any, any>;
    };
    parent?: ProxyDraft | null;
    key?: string | number | symbol;
    setMap?: Map<any, ProxyDraft>;
    assignedMap?: Map<any, boolean>;
    callbacks?: ((patches?: Patches, inversePatches?: Patches) => void)[];
}
interface IPatch {
    op: (typeof Operation)[keyof typeof Operation];
    value?: any;
}
export declare type Patch<P extends PatchesOptions = any> = P extends {
    pathAsArray: false;
} ? IPatch & {
    path: string;
} : P extends true | object ? IPatch & {
    path: (string | number)[];
} : IPatch & {
    path: string | (string | number)[];
};
export declare type Patches<P extends PatchesOptions = any> = Patch<P>[];
export declare type Result<T extends any, O extends PatchesOptions, F extends boolean> = O extends true | object ? [F extends true ? Immutable<T> : T, Patches<O>, Patches<O>] : F extends true ? Immutable<T> : T;
export declare type CreateResult<T extends any, O extends PatchesOptions, F extends boolean, R extends void | Promise<void> | T | Promise<T>> = R extends Promise<void> | Promise<T> ? Promise<Result<T, O, F>> : Result<T, O, F>;
declare type BaseMark = null | undefined | DataType;
declare type MarkWithCopy = BaseMark | (() => any);
export declare type Mark<O extends PatchesOptions, F extends boolean> = (target: any, types: typeof dataTypes) => O extends true | object ? BaseMark : F extends true ? BaseMark : MarkWithCopy;
export interface Options<O extends PatchesOptions, F extends boolean> {
    /**
     * In strict mode, Forbid accessing non-draftable values and forbid returning a non-draft value.
     */
    strict?: boolean;
    /**
     * Enable patch, and return the patches and inversePatches.
     */
    enablePatches?: O;
    /**
     * Enable autoFreeze, and return frozen state.
     */
    enableAutoFreeze?: F;
    /**
     * Set a mark to determine if the object is mutable or if an instance is an immutable.
     * And it can also return a shallow copy function(AutoFreeze and Patches should both be disabled).
     */
    mark?: Mark<O, F>;
}
export interface ExternalOptions<O extends PatchesOptions, F extends boolean> {
    /**
     * In strict mode, Forbid accessing non-draftable values and forbid returning a non-draft value.
     */
    strict?: boolean;
    /**
     * Enable patch, and return the patches and inversePatches.
     */
    enablePatches?: O;
    /**
     * Enable autoFreeze, and return frozen state.
     */
    enableAutoFreeze?: F;
    /**
     * Set a mark to determine if the object is mutable or if an instance is an immutable.
     * And it can also return a shallow copy function(AutoFreeze and Patches should both be disabled).
     */
    mark?: Mark<O, F>[] | Mark<O, F>;
}
declare type Primitive = string | number | bigint | boolean | null | undefined;
declare type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>;
declare type ImmutableSet<T> = ReadonlySet<Immutable<T>>;
declare type ImmutableObject<T> = {
    readonly [K in keyof T]: Immutable<T[K]>;
};
export declare type IfAvailable<T, Fallback = void> = true | false extends (T extends never ? true : false) ? Fallback : keyof T extends never ? Fallback : T;
declare type WeakReferences = IfAvailable<WeakMap<any, any>> | IfAvailable<WeakSet<any>>;
declare type AtomicObject = Function | Promise<any> | Date | RegExp;
export declare type Immutable<T> = T extends Primitive | AtomicObject ? T : T extends IfAvailable<ReadonlyMap<infer K, infer V>> ? ImmutableMap<K, V> : T extends IfAvailable<ReadonlySet<infer V>> ? ImmutableSet<V> : T extends WeakReferences ? T : T extends object ? ImmutableObject<T> : T;
declare type DraftedMap<K, V> = Map<K, Draft<V>>;
declare type DraftedSet<T> = Set<Draft<T>>;
declare type DraftedObject<T> = {
    -readonly [K in keyof T]: Draft<T[K]>;
};
export declare type Draft<T> = T extends Primitive | AtomicObject ? T : T extends IfAvailable<ReadonlyMap<infer K, infer V>> ? DraftedMap<K, V> : T extends IfAvailable<ReadonlySet<infer V>> ? DraftedSet<V> : T extends WeakReferences ? T : T extends object ? DraftedObject<T> : T;
export {};
