"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getElementsForSourceLine = getElementsForSourceLine;
exports.getElementBounds = getElementBounds;
exports.scrollToRevealSourceLine = scrollToRevealSourceLine;
exports.getEditorLineNumberForOffset = getEditorLineNumberForOffset;
exports.getLineElementsAtPageOffset = getLineElementsAtPageOffset;
function getElementsForSourceLine(targetLine, lines) {
    const lineNumber = Math.floor(targetLine);
    let previous = lines[0] || null;
    for (const entry of lines) {
        if (entry.line === lineNumber) {
            return { previous: entry, next: undefined };
        }
        else if (entry.line > lineNumber) {
            return { previous, next: entry };
        }
        previous = entry;
    }
    return { previous };
}
function getElementBounds({ el: element }) {
    // Some code line elements may contain other code line elements.
    // In those cases, only take the height up to that child.
    const codeLineChild = element.querySelector(`.line`);
    if (codeLineChild) {
        const height = Math.max(1, codeLineChild.offsetTop - element.offsetTop);
        return {
            top: element.offsetTop,
            height,
        };
    }
    return { top: element.offsetTop, height: element.offsetHeight };
}
function scrollToRevealSourceLine(line, lines, outerRef) {
    const outer = outerRef.current;
    if (!outer)
        return;
    if (line <= 0) {
        outer.scroll(outer.scrollLeft, 0);
        return;
    }
    const { previous, next } = getElementsForSourceLine(line, lines);
    if (!previous) {
        return;
    }
    let scrollTo = 0;
    const rect = getElementBounds(previous);
    const previousTop = rect.top;
    if (next && next.line !== previous.line) {
        // Between two elements. Go to percentage offset between them.
        const betweenProgress = (line - previous.line) / (next.line - previous.line);
        const previousEnd = previousTop + rect.height;
        const betweenHeight = next.el.offsetTop - previousEnd;
        scrollTo = previousEnd + betweenProgress * betweenHeight;
    }
    else {
        const progressInElement = line - Math.floor(line);
        scrollTo = previousTop + rect.height * progressInElement;
    }
    scrollTo = Math.abs(scrollTo) < 1 ? Math.sign(scrollTo) : scrollTo;
    outer.scroll(outer.scrollLeft, Math.max(1, scrollTo));
}
function getEditorLineNumberForOffset(offset, lines, outerRef) {
    if (!outerRef.current)
        return null;
    const { previous, next } = getLineElementsAtPageOffset(offset, lines, outerRef);
    if (previous) {
        if (previous.line < 0) {
            return 0;
        }
        const previousBounds = getElementBounds(previous);
        const offsetFromPrevious = offset - previousBounds.top;
        if (next) {
            const progressBetweenElements = offsetFromPrevious / (getElementBounds(next).top - previousBounds.top);
            return previous.line + progressBetweenElements * (next.line - previous.line);
        }
        else {
            const progressWithinElement = offsetFromPrevious / previousBounds.height;
            return previous.line + progressWithinElement;
        }
    }
    return null;
}
function getLineElementsAtPageOffset(offset, lines, outerRef) {
    const outer = outerRef.current;
    if (!outer)
        return { previous: null };
    const position = offset;
    let lo = -1;
    let hi = lines.length - 1;
    while (lo + 1 < hi) {
        const mid = Math.floor((lo + hi) / 2);
        const bounds = getElementBounds(lines[mid]);
        if (bounds.top + bounds.height >= position) {
            hi = mid;
        }
        else {
            lo = mid;
        }
    }
    const hiElement = lines[hi];
    const hiBounds = getElementBounds(hiElement);
    if (hi >= 1 && hiBounds.top > position) {
        const loElement = lines[lo];
        return { previous: loElement, next: hiElement };
    }
    if (hi > 1 && hi < lines.length && hiBounds.top + hiBounds.height > position) {
        return { previous: hiElement, next: lines[hi + 1] };
    }
    return { previous: hiElement };
}
//# sourceMappingURL=sync-scroll.js.map
