"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UiHandle = void 0;
const constants_1 = require("../../../../../json-crdt-extensions/peritext/rga/constants");
class UiHandle {
    constructor(txt, api) {
        this.txt = txt;
        this.api = api;
    }
    point(pos) {
        return typeof pos === 'number' ? this.txt.pointAt(pos) : pos;
    }
    /**
     * Finds the position of the character at the given point (position between
     * characters). The first position has index of 0. Have to specify the
     * direction of the search, forward or backward.
     *
     * @param point The index of the character in the text, or a {@link Point}.
     * @param fwd Whether to find the location of the next character after the
     *     given {@link Point} or before, defaults to `true`.
     * @returns The bounding rectangle of the character at the given index.
     */
    getPointRect(pos, right = true) {
        const txt = this.txt;
        const point = typeof pos === 'number' ? txt.pointAt(pos) : pos.clone();
        if (right)
            point.refBefore();
        else
            point.refAfter();
        return this.api.getCharRect?.(point.id);
    }
    pointX(pos) {
        const txt = this.txt;
        const point = typeof pos === 'number' ? txt.pointAt(pos) : pos;
        const rect = this.getPointRect(point, point.anchor === constants_1.Anchor.Before);
        if (!rect)
            return;
        const x = point.anchor === constants_1.Anchor.Before ? rect.x : rect.x + rect.width;
        return [x, rect];
    }
    findPointAtX(targetX, line) {
        let point = line[0][0].clone();
        const curr = point;
        let bestDiff = 1e9;
        const max = line[1][0].viewPos() - line[0][0].viewPos();
        if (!this.api.getCharRect)
            return point;
        for (let i = 0; i < max; i++) {
            const pointX = this.pointX(curr);
            if (!pointX)
                break;
            const [x] = pointX;
            const diff = Math.abs(x - targetX);
            if (diff <= bestDiff) {
                bestDiff = diff;
                point = curr.clone();
            }
            else
                break;
            curr.step(1);
        }
        return point;
    }
    getLineEnd(pos, right = true) {
        const startPoint = this.point(pos);
        if (startPoint.isAbs())
            return;
        const startRect = this.getPointRect(startPoint, right);
        if (!startRect)
            return;
        let curr = startPoint.clone();
        let currRect = startRect;
        const prepareReturn = () => {
            if (right) {
                curr.step(1);
                curr.refAfter();
            }
            else {
                curr.step(-1);
                curr.refBefore();
            }
            return [curr, currRect];
        };
        while (true) {
            const next = curr.copy((p) => p.step(right ? 1 : -1));
            if (!next)
                return prepareReturn();
            if (next.isAbs())
                return prepareReturn();
            const nextRect = this.getPointRect(next, right);
            if (!nextRect)
                return prepareReturn();
            if (right ? nextRect.x < currRect.x : nextRect.x > currRect.x)
                return prepareReturn();
            curr = next;
            currRect = nextRect;
        }
    }
    getLineInfo(pos) {
        const txt = this.txt;
        const point = this.point(pos);
        if (point.isAbs())
            return;
        const isEndOfText = point.viewPos() === txt.strApi().length();
        if (isEndOfText)
            return;
        const left = this.getLineEnd(point, false);
        const right = this.getLineEnd(point, true);
        if (!left || !right)
            return;
        return [left, right];
    }
    getNextLineInfo(line, direction = 1) {
        const edge = line[direction > 0 ? 1 : 0][0];
        const txt = this.txt;
        if (edge.viewPos() >= txt.str.length())
            return;
        const point = edge.copy((p) => p.step(direction));
        const success = txt.overlay.skipMarkers(point, direction);
        if (!success)
            return;
        if (point.isAbs())
            return;
        return this.getLineInfo(point);
    }
}
exports.UiHandle = UiHandle;
//# sourceMappingURL=UiHandle.js.map