/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { FieldKey, ProtoNodes, UpPath } from "../../core";
import { Events, ISubscribable } from "../../events";
import { EditableTree } from "./editableTreeTypes";
/**
 * Binder events reflecting atomic data operations
 * @public
 */
export interface OperationBinderEvents {
    delete(context: DeleteBindingContext): void;
    insert(context: InsertBindingContext): void;
    batch(context: BatchBindingContext): void;
}
/**
 * Binder events signaling state invalidation
 * @public
 */
export interface InvalidationBinderEvents {
    invalidation(context: InvalidationBindingContext): void;
}
/**
 * Compare function, generic.
 *
 * @public
 */
export declare type CompareFunction<T> = (a: T, b: T) => number;
/**
 * Compare function for binder events.
 *
 * @public
 */
export declare type BinderEventsCompare = CompareFunction<VisitorBindingContext>;
/**
 * Compare function for anchors.
 *
 * @public
 */
export declare type AnchorsCompare = CompareFunction<UpPath>;
/**
 * Options to configure binder behavior.
 *
 * TODO: add more options:
 * `filterFn?: (context: BindingContext) => boolean;`
 * `pathPolicy?: "relative" | "absolute";`
 * @public
 */
export interface BinderOptions {
    sortFn?: BinderEventsCompare;
}
/**
 * Specialized binder options for flushable binders.
 *
 * @public
 */
export interface FlushableBinderOptions<E extends Events<E>> extends BinderOptions {
    autoFlush: boolean;
    autoFlushPolicy: keyof Events<E>;
    sortAnchorsFn?: AnchorsCompare;
}
/**
 * Match policy for binding: subtree or path.
 *
 * - `subtree` match policy means that path filtering would return events matching the exact path and its subpaths,
 * ie. changes to (nested) children would be allowed to bubble up to parent listeners.
 * - {@link SubtreePolicy} match policy is  equivalent with `subtree` match policy, while allowing to specify a maximum
 * depth for the subtree.
 * - `path` match policy means that path filtering would return events matching the _exact_ path only. In this case
 * _exact_ semantics include interpreting an `undefined` _index_ field in the {@link PathStep} as a wildcard.
 *
 *
 * @public
 */
export declare type MatchPolicy = SubtreePolicy | "subtree" | "path";
/**
 * Subtree match policy where max depth can be specified.
 *
 * @public
 */
export interface SubtreePolicy {
    maxDepth: number;
}
/**
 * The data binder interface
 *
 * @public
 */
export interface DataBinder<B extends OperationBinderEvents | InvalidationBinderEvents> {
    /**
     * Register an event listener
     *
     * @param anchor - The anchor to register the listener on
     * @param eventType - The {@link BindingType} to listen for.
     * @param eventTrees - The {@link BindPolicy}s to filter on.
     * @param listener - The listener to register
     */
    register<K extends keyof Events<B>>(anchor: EditableTree, eventType: K, eventTrees: BindPolicy[], listener?: B[K]): void;
    /**
     * Unregister all listeners.
     */
    unregisterAll(): void;
}
/**
 * An interface describing the ability to flush.
 *
 * @public
 */
export interface Flushable<T> {
    flush(): T;
}
/**
 * An interface describing a flushable data binder.
 *
 * @public
 */
export interface FlushableDataBinder<B extends OperationBinderEvents | InvalidationBinderEvents> extends DataBinder<B>, Flushable<FlushableDataBinder<B>> {
}
/**
 * A step in a bind path
 *
 * @public
 */
export interface PathStep {
    /**
     * The field being traversed
     */
    readonly field: FieldKey;
    /**
     * The index of the element being navigated to
     */
    readonly index?: number;
}
/**
 * The default type for a bind tree
 *
 * @public
 */
export declare type BindTreeDefault = BindTree;
/**
 * A bind tree is a compact representation of related {@link BindPath}s.
 *
 * @public
 */
export interface BindTree<T = BindTreeDefault> extends PathStep {
    readonly children: Map<FieldKey, T>;
}
/**
 * A bind policy is a combination of a {@link BindTree} and a {@link MatchPolicy}.
 *
 * @public
 */
export interface BindPolicy {
    readonly bindTree: BindTree;
    readonly matchPolicy: MatchPolicy;
}
/**
 * Index symbol for syntax tree
 *
 * @public
 */
export declare const indexSymbol: unique symbol;
/**
 * A syntax node for the bind language
 *
 * The bind language is a compact representation of related {@link BindPath}s. It can be used to
 * simplify usage and construction of {@link BindTree}s.
 *
 * see {@link BindTree}
 * see {@link compileSyntaxTree}
 *
 * @public
 */
export interface BindSyntaxTree {
    readonly [indexSymbol]?: number;
    readonly [key: string]: true | BindSyntaxTree;
}
/**
 * A top down path in a bind or path tree is a collection of {@link PathStep}s
 *
 * see {@link BindTree}
 * see {@link UpPath}
 *
 * @public
 */
export declare type DownPath = PathStep[];
/**
 * A bind path is a top down path in a bind tree
 *
 * @public
 */
export declare type BindPath = DownPath;
/**
 * A binding context specialized for {@link PathVisitor} triggered binding events.
 *
 * @public
 */
export declare type VisitorBindingContext = DeleteBindingContext | InsertBindingContext;
/**
 * Enumeration of binding categories
 *
 * @public
 */
export declare const BindingType: {
    readonly Delete: "delete";
    readonly Insert: "insert";
    readonly Invalidation: "invalidation";
    readonly Batch: "batch";
};
/**
 * The type of a binding context
 *
 * @public
 */
export declare type BindingContextType = typeof BindingType[keyof typeof BindingType];
/**
 * The binding context attribution common to all binding events
 *
 * @public
 */
export interface BindingContext {
    readonly type: BindingContextType;
}
/**
 * The binding context for a delete event
 *
 * @public
 */
export interface DeleteBindingContext extends BindingContext {
    readonly type: typeof BindingType.Delete;
    readonly path: UpPath;
    readonly count: number;
}
/**
 * The binding context for an insert event
 *
 * @public
 */
export interface InsertBindingContext extends BindingContext {
    readonly type: typeof BindingType.Insert;
    readonly path: UpPath;
    readonly content: ProtoNodes;
}
/**
 * The binding context for an invalidation event
 *
 * @public
 */
export interface InvalidationBindingContext extends BindingContext {
    readonly type: typeof BindingType.Invalidation;
}
/**
 * The binding context for a batch event
 *
 * @public
 */
export interface BatchBindingContext extends BindingContext {
    readonly type: typeof BindingType.Batch;
    readonly events: VisitorBindingContext[];
}
/**
 * Compute a top-town {@link DownPath} from an {@link UpPath}.
 *
 * @public
 */
export declare function toDownPath(upPath: UpPath): DownPath;
/**
 * Create a buffering data binder.
 *
 * @public
 */
export declare function createDataBinderBuffering<E extends Events<E>>(view: ISubscribable<E>, options: FlushableBinderOptions<E>): FlushableDataBinder<OperationBinderEvents>;
/**
 * Create a direct data binder.
 *
 * @public
 */
export declare function createDataBinderDirect<E extends Events<E>>(view: ISubscribable<E>, options: BinderOptions): DataBinder<OperationBinderEvents>;
/**
 * Create an invalidating data binder.
 *
 * @public
 */
export declare function createDataBinderInvalidating<E extends Events<E>>(view: ISubscribable<E>, options: FlushableBinderOptions<E>): FlushableDataBinder<InvalidationBinderEvents>;
/**
 * Create binder options. If not specified, the default values are:
 * - sortFn: no sorting
 *
 * @public
 */
export declare function createBinderOptions({ sortFn }: {
    sortFn?: BinderEventsCompare;
}): BinderOptions;
/**
 * Create flushable binder options. If not specified, the default values are:
 * - sortFn: no sorting
 * - sortAnchorsFn: no sorting
 * - autoFlush: true
 *
 * @public
 */
export declare function createFlushableBinderOptions<E extends Events<E>>({ sortFn, sortAnchorsFn, autoFlush, autoFlushPolicy, }: {
    sortFn?: BinderEventsCompare;
    sortAnchorsFn?: AnchorsCompare;
    autoFlush?: boolean;
    autoFlushPolicy: keyof Events<E>;
}): FlushableBinderOptions<E>;
/**
 * Utility to create a compare function from a list of compare functions.
 *
 * @param fns - a list of compare functions
 * @returns a compare function that can be used for sorting
 * @public
 */
export declare function comparePipeline<T>(...fns: CompareFunction<T>[]): CompareFunction<T>;
/**
 * Compiles a (user friendly) syntax tree into the internal binding structure.
 * The syntax tree is a compact representation of related {@link BindPath}s.
 * The match policy can be specified. If not specified, the default value is "path".
 * @returns a {@link BindPolicy} object
 * @public
 */
export declare function compileSyntaxTree(syntaxTree: BindSyntaxTree, matchPolicy?: MatchPolicy): BindPolicy;
//# sourceMappingURL=editableTreeBinder.d.ts.map