import { FanOut } from 'thingies/lib/fanout';
import { VecNode, ConNode, ObjNode, ArrNode, BinNode, StrNode, ValNode } from '../../nodes';
import { type ApiPath, ArrApi, BinApi, ConApi, type NodeApi, ObjApi, StrApi, VecApi, ValApi } from './nodes';
import type { Patch } from '../../../json-crdt-patch/Patch';
import { PatchBuilder } from '../../../json-crdt-patch/PatchBuilder';
import type { SyncStore } from '../../../util/events/sync-store';
import { MergeFanOut, MicrotaskBufferFanOut } from './fanout';
import { ExtNode } from '../../extensions/ExtNode';
import type { Model } from '../Model';
import type { JsonNode, JsonNodeView } from '../../nodes';
/**
 * Local changes API for a JSON CRDT model. This class is the main entry point
 * for executing local user actions on a JSON CRDT document.
 *
 * @category Local API
 */
export declare class ModelApi<N extends JsonNode = JsonNode> implements SyncStore<JsonNodeView<N>> {
    readonly model: Model<N>;
    /**
     * Patch builder for the local changes.
     */
    builder: PatchBuilder;
    /**
     * Index of the next operation in builder's patch to be committed locally.
     *
     * @ignore
     */
    next: number;
    /** Emitted before the model is reset, using the `.reset()` method. */
    readonly onBeforeReset: FanOut<void>;
    /** Emitted after the model is reset, using the `.reset()` method. */
    readonly onReset: FanOut<void>;
    /** Emitted before a patch is applied using `model.applyPatch()`. */
    readonly onBeforePatch: FanOut<Patch>;
    /** Emitted after a patch is applied using `model.applyPatch()`. */
    readonly onPatch: FanOut<Patch>;
    /** Emitted before local changes through `model.api` are applied. */
    readonly onBeforeLocalChange: FanOut<number>;
    /** Emitted after local changes through `model.api` are applied. */
    readonly onLocalChange: FanOut<number>;
    /**
     * Emitted after local changes through `model.api` are applied. Same as
     * `.onLocalChange`, but this event buffered withing a microtask.
     */
    readonly onLocalChanges: MicrotaskBufferFanOut<number>;
    /** Emitted before a transaction is started. */
    readonly onBeforeTransaction: FanOut<void>;
    /** Emitted after transaction completes. */
    readonly onTransaction: FanOut<void>;
    /** Emitted when the model changes. Combines `onReset`, `onPatch` and `onLocalChange`. */
    readonly onChange: MergeFanOut<number | Patch | undefined>;
    /** Emitted when the model changes. Same as `.onChange`, but this event is emitted once per microtask. */
    readonly onChanges: MicrotaskBufferFanOut<number | Patch | undefined>;
    /** Emitted when the `model.api` builder change buffer is flushed. */
    readonly onFlush: FanOut<Patch>;
    /**
     * @param model Model instance on which the API operates.
     */
    constructor(model: Model<N>);
    /**
     * Returns a local change API for the given node. If an instance already
     * exists, returns the existing instance.
     */
    wrap(node: ValNode): ValApi;
    wrap(node: StrNode<any>): StrApi;
    wrap(node: BinNode): BinApi;
    wrap(node: ArrNode): ArrApi;
    wrap(node: ObjNode): ObjApi;
    wrap(node: ConNode): ConApi;
    wrap(node: VecNode): VecApi;
    wrap(node: JsonNode): NodeApi;
    wrap(node: ExtNode<any, any>): NodeApi;
    /**
     * Local changes API for the root node.
     */
    get r(): ValApi<import("../../nodes").RootNode<N>>;
    /** @ignore */
    get node(): import("./types").JsonNodeApi<N>;
    /**
     * Traverses the model starting from the root node and returns a local
     * changes API for a node at the given path.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for a node at the given path.
     */
    in(path?: ApiPath): ValApi<ValNode<any>>;
    /**
     * Locates a JSON CRDT node, throws an error if the node doesn't exist.
     *
     * @param path Path at which to locate a node.
     * @returns A JSON CRDT node.
     */
    find(path?: ApiPath): JsonNode<unknown>;
    /**
     * Locates a `con` node and returns a local changes API for it. If the node
     * doesn't exist or the node at the path is not a `con` node, throws an error.
     *
     * @todo Rename to `con`.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for a `con` node.
     */
    con(path?: ApiPath): ConApi<ConNode<any>>;
    /**
     * Locates a `val` node and returns a local changes API for it. If the node
     * doesn't exist or the node at the path is not a `val` node, throws an error.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for a `val` node.
     */
    val(path?: ApiPath): ValApi<ValNode<any>>;
    /**
     * Locates a `vec` node and returns a local changes API for it. If the node
     * doesn't exist or the node at the path is not a `vec` node, throws an error.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for a `vec` node.
     */
    vec(path?: ApiPath): VecApi<VecNode<any>>;
    /**
     * Locates an `obj` node and returns a local changes API for it. If the node
     * doesn't exist or the node at the path is not an `obj` node, throws an error.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for an `obj` node.
     */
    obj(path?: ApiPath): ObjApi<ObjNode<any>>;
    /**
     * Locates a `str` node and returns a local changes API for it. If the node
     * doesn't exist or the node at the path is not a `str` node, throws an error.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for a `str` node.
     */
    str(path?: ApiPath): StrApi;
    /**
     * Locates a `bin` node and returns a local changes API for it. If the node
     * doesn't exist or the node at the path is not a `bin` node, throws an error.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for a `bin` node.
     */
    bin(path?: ApiPath): BinApi;
    /**
     * Locates an `arr` node and returns a local changes API for it. If the node
     * doesn't exist or the node at the path is not an `arr` node, throws an error.
     *
     * @param path Path at which to locate a node.
     * @returns A local changes API for an `arr` node.
     */
    arr(path?: ApiPath): ArrApi<ArrNode<any>>;
    /**
     * Given a JSON/CBOR value, constructs CRDT nodes recursively out of it and
     * sets the root node of the model to the constructed nodes.
     *
     * @param json JSON/CBOR value to set as the view of the model.
     * @returns Reference to itself.
     */
    root(json: unknown): this;
    /**
     * Apply locally any operations from the `.builder`, which haven't been
     * applied yet.
     */
    apply(): void;
    /**
     * Advance patch pointer to the end without applying the operations. With the
     * idea that they have already been applied locally.
     *
     * You need to manually call `this.onBeforeLocalChange.emit(this.next)` before
     * calling this method.
     *
     * @ignore
     */
    advance(): void;
    /**
     * Returns the view of the model.
     *
     * @returns JSON/CBOR of the model.
     */
    view(): Readonly<JsonNodeView<N>>;
    private inTx;
    transaction(callback: () => void): void;
    /**
     * Flushes the builder and returns a patch.
     *
     * @returns A JSON CRDT patch.
     * @todo Make this return undefined if there are no operations in the builder.
     */
    flush(): Patch;
    stopAutoFlush?: () => void;
    /**
     * Begins to automatically flush buffered operations into patches, grouping
     * operations by microtasks or by transactions. To capture the patch, listen
     * to the `.onFlush` event.
     *
     * @returns Callback to stop auto flushing.
     */
    autoFlush(drainNow?: boolean): () => void;
    readonly subscribe: (callback: () => void) => import("thingies/lib/fanout").FanOutUnsubscribe;
    readonly getSnapshot: () => JsonNodeView<N>;
}
