import { Type } from '../type/types';
import { ExtractPaths } from '../common-types/types';
import { FlatObject } from '../flat/types';
export declare enum Operations {
    '$set' = "$set",
    '$unset' = "$unset",
    '$leave' = "$leave",
    '$pull' = "$pull",
    '$push' = "$push",
    '$concat' = "$concat"
}
export type OperationsName = keyof typeof Operations;
export type OperationFn = (source: any, params: any) => boolean;
export declare enum MergeChangeKind {
    MERGE = "merge",// cloning
    PATCH = "patch",// change in source value
    UPDATE = "update"
}
export type MergeMethodName = `${Type}_${Type}`;
export type MergeFn = (first: any, second: any, kind: MergeChangeKind, mc: MergeChangeFn) => unknown;
export type MergeMethods = Partial<Record<MergeMethodName, MergeFn>>;
export interface Mergeable {
    Object: {
        [key: string | number | symbol]: any;
    } & {
        toJSON?: never;
        length?: never;
        call?: never;
        apply?: never;
        prototype?: never;
        [Symbol.match]?: never;
        [Symbol.iterator]?: never;
    };
}
type IsMergeable<T> = T extends Mergeable[keyof Mergeable] ? true : false;
type StripOperations<T> = IsMergeable<T> extends true ? {
    [K in Exclude<keyof T, OperationsName>]: StripOperations<T[K]>;
} : T;
export type Merged<T, U> = RequiredDeep<U extends undefined ? never : IsMergeable<T> extends true ? IsMergeable<U> extends true ? {
    [K in keyof T]: K extends keyof T & keyof U ? Merged<T[K], U[K]> : K extends keyof T ? T[K] : K extends keyof U ? StripOperations<U[K]> : never;
} : U : IsMergeable<U> extends true ? {
    [Z in Exclude<keyof U, OperationsName>]: StripOperations<U[Z]>;
} : U>;
export type MergedAll<T extends any[]> = T extends [infer First, infer Second, ...infer Rest] ? Rest extends any[] ? MergedAll<[Merged<First, Second>, ...Rest]> : Merged<First, Second> : T extends [infer Only] ? Only : never;
export type MergeChangeFn = <T extends any[]>(...values: T) => MergedAll<T>;
export type PartialDeep<T> = T | (T extends (...args: any) => any ? T : T extends (infer U)[] ? PartialDeep<U>[] : IsMergeable<T> extends true ? {
    [K in keyof T]?: PartialDeep<T[K]>;
} : T);
export type PatchOperation<T> = {
    $set?: Partial<T | FlatObject<T>>;
    $unset?: ExtractPaths<T, '.'>[];
    $leave?: ExtractPaths<T, '.'>[];
    $pull?: Record<ExtractPaths<T, '.'>, unknown>;
    $push?: Record<ExtractPaths<T, '.'>, unknown>;
    $concat?: Record<ExtractPaths<T, '.'>, unknown>;
};
export type Patch<T> = T extends BuildIn ? T : T extends (infer U)[] ? Patch<U>[] : IsMergeable<T> extends true ? {
    [K in keyof T]?: Patch<T[K]>;
} & PatchOperation<T> : Exclude<T, undefined>;
export type Function = (...args: any) => any;
export type BuildIn = string | number | boolean | bigint | symbol | null | undefined | void | Date | RegExp | Function | Promise<any>;
export type RequiredDeep<T> = T extends BuildIn ? T : T extends ReadonlyArray<infer U> ? RequiredDeep<NonNullable<U>>[] : T extends Array<infer U> ? RequiredDeep<NonNullable<U>>[] : T extends Map<infer K, infer V> ? Map<RequiredDeep<NonNullable<K>>, RequiredDeep<NonNullable<V>>> : T extends Set<infer U> ? Set<RequiredDeep<NonNullable<U>>> : T extends object ? {
    [K in keyof T]-?: RequiredDeep<NonNullable<T[K]>>;
} : T;
export {};
