import { Delta } from 'jsondiffpatch';
import { KeyOfValueWithType } from 'tslang';
import { IContext } from '../context';
import { AccessRight, ISyncable, ISyncableObject, RefDictToSyncableObjectDict, SyncableContainer, SyncableRef } from '../syncable';
import { NumericTimestamp } from '../types';
import { ChangePacket, ChangePacketId, GeneralChange, IChange, SyncableCreationRef } from './change';
export declare type RefDictToSyncableOrCreationRefDict<T extends object> = T extends object ? {
    [TName in KeyOfValueWithType<Required<T>, SyncableRef>]: NonNullable<T[TName]> extends SyncableRef<infer TSyncableObject> ? TSyncableObject['syncable'] | (undefined extends T[TName] ? undefined : never) : never;
} & {
    [TName in KeyOfValueWithType<Required<T>, SyncableRef[]>]: NonNullable<T[TName]> extends SyncableRef<infer TSyncableObject>[] ? TSyncableObject['syncable'][] | (undefined extends T[TName] ? undefined : never) : never;
} & {
    [TName in KeyOfValueWithType<Required<T>, SyncableCreationRef>]: T[TName];
} : never;
declare type ChangeToSyncableObjectRefDict<T extends IChange> = RefDictToSyncableObjectDict<T['refs']>;
declare type ChangeToSyncableOrCreationRefDict<T extends IChange> = RefDictToSyncableOrCreationRefDict<T['refs']>;
export interface ChangePlantProcessingResultUpdateItem {
    delta: Delta;
    snapshot: ISyncable;
}
export interface ChangePlantProcessingResult {
    id: ChangePacketId;
    creations: ISyncable[];
    updates: ChangePlantProcessingResultUpdateItem[];
    removals: SyncableRef[];
    notifications: unknown[];
    changes: GeneralChange[];
}
export interface ChangePlantProcessingResultWithClock extends ChangePlantProcessingResult {
    clock: number;
}
export declare type ChangePlantProcessorCreateOperation = (creation: ISyncable) => void;
export declare type ChangePlantProcessorRemoveOperation = (object: ISyncableObject) => void;
export declare type ChangePlantProcessorIsBeingRemovedTest = (object: ISyncableObject) => boolean;
export declare type ChangePlantProcessorGrantOperation = <TSyncableObject extends ISyncableObject>(object: TSyncableObject, fieldNames: Extract<keyof TSyncableObject['syncable'], string>[], rights: AccessRight[]) => void;
export declare type ChangePlantProcessorAbortOperation = () => void;
export declare type ChangePlantProcessorChangeOperation<TChange = GeneralChange> = (change: TChange) => void;
export declare type ChangePlantProcessorPrepareOperation = <T extends ISyncableObject>(object: T) => T['syncable'];
export declare type ChangePlantProcessorNotifyOperation<TNotification = unknown> = (notification: TNotification) => void;
export interface ChangePlantProcessorExtra<TGenericParams extends IChangePlantBlueprintGenericParams = GeneralChangePlantBlueprintGenericParams, TSpecificChange extends IChange = TGenericParams['change']> {
    context: TGenericParams['context'];
    container: SyncableContainer<TGenericParams['syncableObject']>;
    type: TSpecificChange['type'];
    refs: TSpecificChange['refs'];
    options: TSpecificChange['options'];
    create: ChangePlantProcessorCreateOperation;
    remove: ChangePlantProcessorRemoveOperation;
    isBeingRemoved: ChangePlantProcessorIsBeingRemovedTest;
    grant: ChangePlantProcessorGrantOperation;
    prepare: ChangePlantProcessorPrepareOperation;
    abort: ChangePlantProcessorAbortOperation;
    change: ChangePlantProcessorChangeOperation<TGenericParams['change']>;
    notify: ChangePlantProcessorNotifyOperation<TGenericParams['notification']>;
    createdAt: NumericTimestamp;
}
export declare type ChangePlantResolver<TGenericParams extends IChangePlantBlueprintGenericParams = GeneralChangePlantBlueprintGenericParams> = (syncables: ChangeToSyncableOrCreationRefDict<TGenericParams['change']>, options: TGenericParams['change']['options']) => SyncableRef<TGenericParams['syncableObject']>[];
declare type ChangePlantSpecificResolver<TGenericParams extends IChangePlantBlueprintGenericParams, TType extends string> = ChangePlantResolver<{
    context: TGenericParams['context'];
    syncableObject: TGenericParams['syncableObject'];
    change: Extract<TGenericParams['change'], {
        type: TType;
    }>;
    notification: TGenericParams['notification'];
}>;
export declare type ChangePlantProcessor<TGenericParams extends IChangePlantBlueprintGenericParams = GeneralChangePlantBlueprintGenericParams, TSpecificChange extends TGenericParams['change'] = TGenericParams['change']> = (syncables: ChangeToSyncableOrCreationRefDict<TSpecificChange>, objects: ChangeToSyncableObjectRefDict<TSpecificChange>, extra: ChangePlantProcessorExtra<TGenericParams, TSpecificChange>) => void;
declare type ChangePlantSpecificProcessor<TGenericParams extends IChangePlantBlueprintGenericParams, TType extends string> = ChangePlantProcessor<{
    context: TGenericParams['context'];
    syncableObject: TGenericParams['syncableObject'];
    change: TGenericParams['change'];
    notification: TGenericParams['notification'];
}, Extract<TGenericParams['change'], {
    type: TType;
}>>;
export interface ChangePlantProcessorOptions<TGenericParams extends IChangePlantBlueprintGenericParams = IChangePlantBlueprintGenericParams> {
    processor: ChangePlantProcessor<TGenericParams>;
    resolver: ChangePlantResolver<TGenericParams>;
}
interface ChangePlantSpecificProcessorOptions<TGenericParams extends IChangePlantBlueprintGenericParams, TType extends string> {
    processor: ChangePlantSpecificProcessor<TGenericParams, TType>;
    resolver: ChangePlantSpecificResolver<TGenericParams, TType>;
}
export declare type ChangePlantBlueprint<TGenericParams extends IChangePlantBlueprintGenericParams = GeneralChangePlantBlueprintGenericParams> = {
    [TType in TGenericParams['change']['type']]: ChangePlantSpecificProcessor<TGenericParams, TType> | ChangePlantSpecificProcessorOptions<TGenericParams, TType>;
};
export interface IChangePlantBlueprintGenericParams {
    context: IContext;
    syncableObject: ISyncableObject;
    change: IChange;
    notification: unknown;
}
export interface GeneralChangePlantBlueprintGenericParams extends IChangePlantBlueprintGenericParams {
    change: GeneralChange;
}
export declare type ChangePlantResolveSyncableLoader = (refs: SyncableRef[]) => Promise<ISyncable[]>;
export declare class ChangePlant {
    private blueprint;
    constructor(blueprint: ChangePlantBlueprint);
    resolve({ type, refs: refDict, options }: ChangePacket, syncables: ISyncable[]): SyncableRef[];
    process(packet: ChangePacket, context: IContext, container: SyncableContainer): ChangePlantProcessingResult;
    process(packet: ChangePacket, context: IContext, container: SyncableContainer, clock: number): ChangePlantProcessingResultWithClock;
}
export {};
