import { normalizeMarkerId } from "../utils";
function bridgeIdsMatch(left, right) {
    const normalizedLeft = normalizeMarkerId(left);
    const normalizedRight = normalizeMarkerId(right);
    return (!!normalizedLeft && !!normalizedRight && normalizedLeft === normalizedRight);
}
export function bridgeSelectionMatchesInteraction(selection, interaction) {
    if (!selection?.activeField)
        return false;
    if (interaction.elementKey && selection.activeField.elementKey) {
        // Element keys identify a particular rendered field instance. Falling back
        // to the field id when both keys are present would let a pre-refresh
        // selection snapshot describe the replacement element.
        return selection.activeField.elementKey === interaction.elementKey;
    }
    return bridgeIdsMatch(selection.activeField.fieldId, interaction.fieldId);
}
function clampTextOffset(value, length) {
    if (typeof value !== "number" || !Number.isFinite(value)) {
        return length;
    }
    return Math.min(length, Math.max(0, value));
}
function getPlainTextFromBridgeValue(value) {
    if (!/[<&]/.test(value))
        return value;
    try {
        const parser = new DOMParser();
        return parser.parseFromString(value, "text/html").body.textContent ?? "";
    }
    catch {
        return value.replace(/<[^>]*>/g, "");
    }
}
function isFiniteOffset(value) {
    return typeof value === "number" && Number.isFinite(value);
}
export function resolveBridgeTextCompletionInput({ rawValue, isRichText, selectedText, liveSelectedText, selectionStartOffset, selectionEndOffset, liveSelectionStartOffset, liveSelectionEndOffset, snapshotSelectionStartOffset, snapshotSelectionEndOffset, contextBefore, contextAfter, }) {
    const hasCompleteLiveOffsets = isFiniteOffset(liveSelectionStartOffset) &&
        isFiniteOffset(liveSelectionEndOffset);
    const plainValue = isRichText
        ? getPlainTextFromBridgeValue(rawValue)
        : rawValue;
    const fallbackSelectionStart = clampTextOffset(isRichText
        ? hasCompleteLiveOffsets
            ? liveSelectionStartOffset
            : undefined
        : selectionStartOffset, plainValue.length);
    const fallbackSelectionEnd = clampTextOffset(isRichText
        ? hasCompleteLiveOffsets
            ? liveSelectionEndOffset
            : undefined
        : (selectionEndOffset ?? selectionStartOffset), plainValue.length);
    const resolveResult = (value, requestSelectionStart, requestSelectionEnd, snapshotSelectedTextIsTrusted = false) => ({
        value,
        requestSelectionStart,
        requestSelectionEnd,
        commandSelectionStart: hasCompleteLiveOffsets
            ? liveSelectionStartOffset
            : requestSelectionStart,
        commandSelectionEnd: hasCompleteLiveOffsets
            ? liveSelectionEndOffset
            : requestSelectionEnd,
        commandSelectedText: hasCompleteLiveOffsets
            ? (liveSelectedText ??
                (liveSelectionStartOffset === liveSelectionEndOffset
                    ? ""
                    : snapshotSelectedTextIsTrusted
                        ? selectedText
                        : undefined))
            : isRichText
                ? ""
                : selectedText,
    });
    if (!isRichText) {
        return resolveResult(rawValue, fallbackSelectionStart, fallbackSelectionEnd);
    }
    const hasSnapshotOffsets = isFiniteOffset(snapshotSelectionStartOffset) &&
        isFiniteOffset(snapshotSelectionEndOffset);
    const snapshotMatchesLiveOffsets = hasCompleteLiveOffsets &&
        hasSnapshotOffsets &&
        snapshotSelectionStartOffset === liveSelectionStartOffset &&
        snapshotSelectionEndOffset === liveSelectionEndOffset;
    const contextMatchesLiveOffsets = hasCompleteLiveOffsets &&
        contextBefore !== undefined &&
        contextBefore.length === liveSelectionStartOffset &&
        contextBefore.length + selectedText.length === liveSelectionEndOffset;
    const reconstructedValue = `${contextBefore ?? ""}${selectedText}${contextAfter ?? ""}`;
    const metadataReconstructsNonemptyValue = reconstructedValue.length > 0 || plainValue.length === 0;
    if ((snapshotMatchesLiveOffsets || contextMatchesLiveOffsets) &&
        (contextBefore !== undefined || contextAfter !== undefined) &&
        metadataReconstructsNonemptyValue) {
        const metadataSelectionStart = contextBefore?.length ?? 0;
        return resolveResult(reconstructedValue, metadataSelectionStart, metadataSelectionStart + selectedText.length, snapshotMatchesLiveOffsets);
    }
    return resolveResult(plainValue, fallbackSelectionStart, fallbackSelectionEnd);
}
//# sourceMappingURL=bridgeTextCompletion.js.map