import { OPERATION } from "../encoding/spec";
import { Schema } from "../Schema";
import { $changes, $decoder, $encoder } from "../types/symbols";
import type { MapSchema } from "../types/custom/MapSchema";
import type { ArraySchema } from "../types/custom/ArraySchema";
import type { CollectionSchema } from "../types/custom/CollectionSchema";
import type { SetSchema } from "../types/custom/SetSchema";
import { Root } from "./Root";
import type { EncodeOperation } from "./EncodeOperation";
import type { DecodeOperation } from "../decoder/DecodeOperation";
declare global {
    interface Object {
        [$changes]?: ChangeTree;
        [$encoder]?: EncodeOperation;
        [$decoder]?: DecodeOperation;
    }
}
export type Ref = Schema | ArraySchema | MapSchema | CollectionSchema | SetSchema;
export type ChangeSetName = "changes" | "allChanges" | "filteredChanges" | "allFilteredChanges";
export interface IndexedOperations {
    [index: number]: OPERATION;
}
export interface ChangeSet {
    indexes: {
        [index: number]: number;
    };
    operations: number[];
    queueRootIndex?: number;
}
export declare function setOperationAtIndex(changeSet: ChangeSet, index: number): void;
export declare function deleteOperationAtIndex(changeSet: ChangeSet, index: number | string): void;
export declare function debugChangeSet(label: string, changeSet: ChangeSet): void;
export declare function enqueueChangeTree(root: Root, changeTree: ChangeTree, changeSet: 'changes' | 'filteredChanges' | 'allFilteredChanges', queueRootIndex?: number): void;
export declare class ChangeTree<T extends Ref = any> {
    ref: T;
    refId: number;
    root?: Root;
    parent?: Ref;
    parentIndex?: number;
    /**
     * Whether this structure is parent of a filtered structure.
     */
    isFiltered: boolean;
    isVisibilitySharedWithParent?: boolean;
    indexedOperations: IndexedOperations;
    changes: ChangeSet;
    allChanges: ChangeSet;
    filteredChanges: ChangeSet;
    allFilteredChanges: ChangeSet;
    indexes: {
        [index: string]: any;
    };
    /**
     * Is this a new instance? Used on ArraySchema to determine OPERATION.MOVE_AND_ADD operation.
     */
    isNew: boolean;
    constructor(ref: T);
    setRoot(root: Root): void;
    setParent(parent: Ref, root?: Root, parentIndex?: number): void;
    forEachChild(callback: (change: ChangeTree, atIndex: number) => void): void;
    operation(op: OPERATION): void;
    change(index: number, operation?: OPERATION): void;
    shiftChangeIndexes(shiftIndex: number): void;
    shiftAllChangeIndexes(shiftIndex: number, startIndex?: number): void;
    private _shiftAllChangeIndexes;
    indexedOperation(index: number, operation: OPERATION, allChangesIndex?: number): void;
    getType(index?: number): any;
    getChange(index: number): OPERATION;
    getValue(index: number, isEncodeAll?: boolean): any;
    delete(index: number, operation?: OPERATION, allChangesIndex?: number): any;
    endEncode(changeSetName: ChangeSetName): void;
    discard(discardAll?: boolean): void;
    /**
     * Recursively discard all changes from this, and child structures.
     */
    discardAll(): void;
    ensureRefId(): void;
    get changed(): boolean;
    protected checkIsFiltered(parent: Ref, parentIndex: number): void;
    protected _checkFilteredByParent(parent: Ref, parentIndex: number): void;
}
