import { Cursor } from './Cursor';
import { EditorSlices } from './EditorSlices';
import { SliceRegistry } from '../registry/SliceRegistry';
import { CommonSliceType, type SliceTypeSteps, type SliceType, type SliceTypeStep } from '../slice';
import { ValueSyncStore } from '../../../util/events/sync-store';
import { UndEndIterator, type UndEndNext } from '../../../util/iterator';
import { type ITimespanStruct } from '../../../json-crdt-patch';
import { CursorAnchor, SliceTypeCon } from '../slice/constants';
import type { Point } from '../rga/Point';
import type { Range } from '../rga/Range';
import type { Printable } from 'tree-dump';
import type { Peritext } from '../Peritext';
import type { MarkerSlice } from '../slice/MarkerSlice';
import type { CharIterator, CharPredicate, EditorPosition, TextRangeUnit, ViewStyle, ViewRange, EditorUi, EditorSelection, MarkerUpdateTarget } from './types';
import type { ApiOperation } from '../../../json-crdt/model/api/types';
export declare class Editor<T = string> implements Printable {
    readonly txt: Peritext<T>;
    readonly saved: EditorSlices<T>;
    readonly extra: EditorSlices<T>;
    readonly local: EditorSlices<T>;
    /**
     * The registry holds definitions of detailed behavior of various slice tags.
     */
    registry: SliceRegistry | undefined;
    /**
     * Formatting basic inline formatting which will be applied to the next
     * inserted text. This is a temporary store for formatting which is not yet
     * applied to the text, but will be if the cursor is not moved. This is used
     * for {@link SliceStacking.One} formatting which is set as "pending" when
     * user toggles it while cursor is caret.
     */
    readonly pending: ValueSyncStore<Map<string | number, unknown> | undefined>;
    constructor(txt: Peritext<T>);
    getRegistry(): SliceRegistry;
    text(): string;
    addCursor(range?: Range<T>, anchor?: CursorAnchor): Cursor<T>;
    /**
     * Cursor is the the current user selection. It can be a caret or a range. If
     * range is collapsed to a single point, it is a *caret*.
     *
     * Returns the first cursor in the text and removes all other cursors. If
     * there is no cursor, creates one and inserts it at the start of the text.
     * To work with multiple cursors, use `.cursors()` method.
     */
    get cursor(): Cursor<T>;
    cursors0(): UndEndNext<Cursor<T>>;
    mainCursor(): Cursor<T> | undefined;
    cursors(): UndEndIterator<Cursor<T>>;
    forCursor(callback: (cursor: Cursor<T>) => void): void;
    /**
     * @returns Returns `true` if there is at least one cursor in the document.
     */
    hasCursor(): boolean;
    /**
     * Returns the first cursor in the document, if any.
     *
     * @returns Returns the first cursor in the document, or `undefined` if there
     *     are no cursors.
     */
    getCursor(): undefined | Cursor<T>;
    /**
     * @returns Returns the exact number of cursors in the document.
     */
    cursorCount(): number;
    /**
     * Returns relative count of cursors (cardinality).
     *
     * @returns 0 if there are no cursors, 1 if there is exactly one cursor, 2 if
     *     there are more than one cursor.
     */
    cursorCard(): 0 | 1 | 2;
    delCursor(cursor: Cursor<T>): void;
    delCursors(): void;
    /**
     * Ensures there is no range selection. If user has selected a range,
     * the contents is removed and the cursor is set at the start of the range
     * as caret.
     */
    collapseCursor(cursor: Range<T>): void;
    collapseCursors(): void;
    /**
     * Ensures there is exactly one cursor. If the cursor is a range, contents
     * inside the range is deleted and cursor is collapsed to a single point.
     *
     * @returns A single cursor collapsed to a single point.
     */
    caret(): Cursor<T>;
    /**
     * Insert inline text at current cursor position. If cursor selects a range,
     * the range is removed and the text is inserted at the start of the range.
     */
    insert0(range: Range<T>, text: string): ITimespanStruct | undefined;
    /**
     * Inserts text at the cursor positions and collapses cursors, if necessary.
     * Then applies any pending inline formatting to the inserted text.
     */
    insert(text: string, ranges?: IterableIterator<Range<T>> | Range<T>[]): ITimespanStruct[];
    /**
     * Deletes the previous character at current cursor positions. If cursors
     * select a range, deletes the whole range.
     */
    del(step?: number): void;
    delRange(range: Range<T>): void;
    /**
     * Deletes one or more units of text in all cursors. If cursor is a range,
     * deletes the whole range.
     *
     * @param step Number of units to delete.
     * @param unit A unit of deletion: "char", "word", "line".
     */
    delete(step: number, unit: 'char' | 'word' | 'line'): void;
    /**
     * Returns an iterator through visible text, one `step`, one character at a
     * time, starting from a given {@link Point}.
     *
     * @param start The starting point.
     * @param step Number of visible characters to skip.
     * @returns The next visible character iterator.
     */
    walk(start: Point<T>, step?: number): CharIterator<T>;
    /**
     * Returns a forward iterator through visible text, one character at a time,
     * starting from a given {@link Point}.
     *
     * @param start The starting point.
     * @param chunk Chunk to start from.
     * @returns The next visible character iterator.
     */
    fwd(start: Point<T>): CharIterator<T>;
    /**
     * Returns a backward iterator through visible text, one character at a time,
     * starting from a given {@link Point}.
     *
     * @param start The starting point.
     * @param chunk Chunk to start from.
     * @returns The previous visible character iterator.
     */
    bwd(start: Point<T>): CharIterator<T>;
    /**
     * Skips a word in an arbitrary direction. A word is defined by the `predicate`
     * function, which returns `true` if the character is part of the word.
     *
     * @param iterator Character iterator.
     * @param predicate Predicate function to match characters, returns `true` if
     *     the character is part of the word.
     * @param firstLetterFound Whether the first letter has already been found. If
     *     not, will skip any characters until the first letter, which is matched
     *     by the `predicate` is found.
     * @returns Point after the last skipped character.
     */
    private skipWord;
    /**
     * Hard skips line, skips to the next "\n" newline character.
     *
     * @param iterator Character iterator.
     * @returns Point after the last skipped character.
     */
    private skipLine;
    /**
     * End of word iterator (eow). Skips a word forward. A word is defined by the
     * `predicate` function, which returns `true` if the character is part of the
     * word.
     *
     * @param point Point from which to start skipping.
     * @param predicate Character class to skip.
     * @param firstLetterFound Whether the first letter has already been found. If
     *        not, will skip any characters until the first letter, which is
     *        matched by the `predicate` is found.
     * @returns Point after the last character skipped.
     */
    eow(point: Point<T>, predicate?: CharPredicate<string>, firstLetterFound?: boolean): Point<T>;
    /**
     * Beginning of word iterator (bow). Skips a word backward. A word is defined
     * by the `predicate` function, which returns `true` if the character is part
     * of the word.
     *
     * @param point Point from which to start skipping.
     * @param predicate Character class to skip.
     * @param firstLetterFound Whether the first letter has already been found. If
     *        not, will skip any characters until the first letter, which is
     *        matched by the `predicate` is found.
     * @returns Point after the last character skipped.
     */
    bow(point: Point<T>, predicate?: CharPredicate<string>, firstLetterFound?: boolean): Point<T>;
    /** Find end of line, starting from given point. */
    eol(point: Point<T>): Point<T>;
    /** Find beginning of line, starting from given point. */
    bol(point: Point<T>): Point<T>;
    /**
     * Find end of block, starting from given point. Overlay should be refreshed
     * before calling this method.
     */
    eob(point: Point<T>): Point<T>;
    /**
     * Find beginning of block, starting from given point. Overlay should be
     * refreshed before calling this method.
     */
    bob(point: Point<T>): Point<T>;
    /**
     * Move a point given number of steps in a specified direction. The unit of
     * one move step is defined by the `unit` parameter.
     *
     * @param point The point to start from.
     * @param steps Number of steps to move. Negative number moves backward.
     * @param unit The unit of move per step: "char", "word", "line", etc.
     * @returns The destination point after the move.
     */
    skip(point: Point<T>, steps: number, unit: TextRangeUnit, ui?: EditorUi<T>): Point<T>;
    /**
     * Move all cursors given number of units.
     *
     * @param steps Number of steps to move.
     * @param unit The unit of move per step: "char", "word", "line".
     * @param endpoint 0 for "focus", 1 for "anchor", 2 for both.
     * @param collapse Whether to collapse the range to a single point.
     */
    move(steps: number, unit: TextRangeUnit, endpoint?: 0 | 1 | 2, collapse?: boolean, ui?: EditorUi<T>): void;
    /**
     * Leaves only the first cursor, and sets it selection to the whole text.
     *
     * @returns Returns `true` if the selection was successful.
     */
    selectAll(): boolean;
    /**
     * Selects a word by extending the selection to the left and right of the point.
     *
     * @param point Point to the right of which is the starting character of the word.
     * @returns Range which contains the word.
     */
    rangeWord(point: Point<T>): Range<T> | undefined;
    /**
     * Returns a range by expanding the selection to the left and right of the
     * given point.
     *
     * @param point Point from which to start range expansion.
     * @param unit Unit of the range expansion.
     * @returns Range which contains the specified unit.
     */
    range(point: Point<T>, unit: TextRangeUnit, ui?: EditorUi<T>): Range<T> | undefined;
    select(unit: TextRangeUnit, ui?: EditorUi<T>): void;
    selectAt(at: EditorPosition<T>, unit: TextRangeUnit | '', ui?: EditorUi<T>): void;
    eraseFormatting(store?: EditorSlices<T>, selection?: Range<T>[] | IterableIterator<Range<T>>): void;
    clearFormatting(store?: EditorSlices<T>, selection?: Range<T>[] | IterableIterator<Range<T>>): void;
    protected toggleRangeExclFmt(range: Range<T>, type: CommonSliceType | string | number, data?: unknown, store?: EditorSlices<T>): void;
    toggleExclFmt(type: SliceTypeCon | string | number, data?: unknown, store?: EditorSlices<T>, selection?: Range<T>[] | IterableIterator<Range<T>>): void;
    /**
     * Returns block split marker of the block inside which the point is located.
     *
     * @param point The point to get the marker at.
     * @returns The split marker at the point, if any.
     */
    getMarker(point: Point<T>): MarkerSlice<T> | undefined;
    /**
     * Returns the block type at the given point. Block type is a nested array of
     * tags, e.g. `['p']`, `['blockquote', 'p']`, `['ul', 'li', 'p']`, etc.
     *
     * @param point The point to get the block type at.
     * @returns Current block type at the point.
     */
    getBlockType(point: Point<T>): [type: SliceTypeSteps, marker?: MarkerSlice<T> | undefined];
    /**
     * Insert a block split at the start of the document. The start of the
     * document is defined as immediately after all deleted characters starting
     * from the beginning of the document, or as the ABS start of the document if
     * there are no deleted characters.
     *
     * @param type The type of the marker.
     * @returns The inserted marker slice.
     */
    insStartMarker(type: SliceTypeSteps): MarkerSlice<T>;
    /**
     * Find the block split marker which contains the point and sets the block
     * type of the marker. If there is no block split marker at the point, a new
     * block split marker is inserted at the beginning of the document with the
     * specified block type.
     *
     * @param point The point at which to set the block type.
     * @param type The new block type.
     * @returns The marker slice at the point, or a new marker slice if there is none.
     */
    setBlockType(point: Point<T>, type: SliceTypeSteps): MarkerSlice<T>;
    getContainerPath(steps: SliceTypeSteps): SliceTypeSteps;
    getDeepestCommonContainer(steps1: SliceTypeSteps, steps2: SliceTypeSteps): number;
    /**
     * @param at Point at which split block split happens.
     * @param slices The slices set to use.
     * @returns True if a marker was inserted, false if it was updated.
     */
    splitAt(at: Point<T>, slices?: EditorSlices<T>): boolean;
    split(type?: SliceType, data?: unknown, selection?: Range<T>[] | IterableIterator<Range<T>>, slices?: EditorSlices<T>): void;
    setStartMarker(type: SliceTypeSteps, data?: unknown, slices?: EditorSlices<T>): MarkerSlice<T>;
    tglMarkerAt(point: Point<T>, type: SliceTypeSteps, data?: unknown, slices?: EditorSlices<T>, def?: SliceTypeStep): void;
    /**
     * Toggle the type of a block split between the slice type and the default
     * (paragraph) block type.
     *
     * @param type Slice type to toggle.
     * @param data Custom data of the slice.
     */
    tglMarker(type: SliceTypeSteps, data?: unknown, selection?: Range<T>[] | IterableIterator<Range<T>>, slices?: EditorSlices<T>, def?: SliceTypeStep): void;
    delMarker(selection?: Range<T>[] | IterableIterator<Range<T>>): void;
    updMarkerSlice(marker: MarkerSlice<T>, target: MarkerUpdateTarget, ops: ApiOperation[]): void;
    updMarkerAt(point: Point<T>, target: MarkerUpdateTarget, ops: ApiOperation[], slices?: EditorSlices<T>): void;
    updMarker(target: MarkerUpdateTarget, ops: ApiOperation[], selection?: Range<T>[] | IterableIterator<Range<T>>, slices?: EditorSlices<T>): void;
    export(range: Range<T>): ViewRange;
    /**
     * "Copy formatting-only", copies inline formatting applied to the selected
     * range.
     *
     * @param range Range copy formatting from, normally a single visible character.
     * @returns A list of serializable inline formatting applied to the selected range.
     */
    exportStyle(range: Range<T>): ViewStyle[];
    import(pos: number, view: ViewRange): number;
    importStyle(range: Range<T>, formatting: ViewStyle[]): void;
    pos2point(at: EditorPosition<T>): Point<T>;
    sel2range(at: EditorSelection<T>): [range: Range<T>, anchor: CursorAnchor];
    end(): Point<T>;
    start(): Point<T>;
    /** ----------------------------------------------------- {@link Printable} */
    toString(tab?: string): string;
}
