import { applyPatch, createPatch, diffWords } from "diff";
function toTimestamp(value) {
    if (!value)
        return 0;
    const timestamp = new Date(value).getTime();
    return Number.isFinite(timestamp) ? timestamp : 0;
}
function matchesFieldSuggestion(suggestion, field) {
    const pageVersion = field.pageItemVersion;
    const versionMatches = pageVersion != null
        ? suggestion.mainItemVersion === pageVersion ||
            suggestion.mainItemVersion === 0
        : suggestion.mainItemVersion === field.version;
    return (suggestion.status === "pending" &&
        suggestion.fieldId === field.fieldId &&
        suggestion.itemId === field.itemId &&
        suggestion.mainItemLanguage === field.language &&
        (!field.pageItemId || suggestion.mainItemId === field.pageItemId) &&
        versionMatches);
}
export function getPendingFieldSuggestions(suggestedEdits, field) {
    return suggestedEdits
        .filter((suggestion) => matchesFieldSuggestion(suggestion, field))
        .sort((left, right) => {
        const timeDelta = toTimestamp(left.created) - toTimestamp(right.created);
        return timeDelta || left.id.localeCompare(right.id);
    });
}
export function getBaselineFieldValue({ repositoryValue, modifiedFields, field, }) {
    const modifiedField = modifiedFields?.find((candidate) => candidate.fieldId === field.fieldId &&
        candidate.item.id === field.itemId &&
        candidate.item.language === field.language &&
        candidate.item.version === field.version);
    return modifiedField ? (modifiedField.value ?? "") : (repositoryValue ?? "");
}
export function mergePendingSuggestionValues(baselineValue, suggestions) {
    let mergedValue = baselineValue;
    for (const suggestion of suggestions) {
        const patch = createPatch("field", suggestion.oldValue, suggestion.newValue);
        const patchedCandidate = applyPatch(mergedValue, patch);
        mergedValue =
            patchedCandidate !== false && typeof patchedCandidate === "string"
                ? patchedCandidate
                : suggestion.newValue;
    }
    return mergedValue;
}
function escapeHtml(value) {
    return value
        .replaceAll("&", "&amp;")
        .replaceAll("<", "&lt;")
        .replaceAll(">", "&gt;")
        .replaceAll('"', "&quot;")
        .replaceAll("'", "&#39;");
}
export function getSuggestionDiffHtml(baselineValue, mergedValue) {
    return diffWords(baselineValue, mergedValue)
        .map((part) => {
        let style = "color: gray;";
        if (part.added) {
            style = "color: green;";
        }
        else if (part.removed) {
            style = "color: red; text-decoration: line-through;";
        }
        return `<span style="${style}">${escapeHtml(part.value)}</span>`;
    })
        .join("");
}
export function getSuggestionDisplayValue({ repositoryValue, modifiedFields, suggestedEdits, field, mode, format = "plain", }) {
    const baselineValue = getBaselineFieldValue({
        repositoryValue,
        modifiedFields,
        field,
    });
    const suggestions = mode === "suggestions"
        ? getPendingFieldSuggestions(suggestedEdits, field)
        : [];
    const mergedValue = suggestions.length
        ? mergePendingSuggestionValues(baselineValue, suggestions)
        : baselineValue;
    const displayValue = mode === "suggestions" && suggestions.length && format === "diff"
        ? getSuggestionDiffHtml(baselineValue, mergedValue)
        : mergedValue;
    return {
        baselineValue,
        mergedValue,
        displayValue,
        suggestions,
        hasSuggestions: suggestions.length > 0,
    };
}
//# sourceMappingURL=suggestionDisplayValue.js.map