"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getEditDiffHistory = getEditDiffHistory;
const edit_1 = require("../../../platform/inlineEdits/common/dataTypes/edit");
const arrays_1 = require("../../../util/vs/base/common/arrays");
const promptCraftingUtils_1 = require("./promptCraftingUtils");
function getEditDiffHistory(activeDoc, xtabHistory, docsInPrompt, computeTokens, { onlyForDocsInPrompt, maxTokens, nEntries, useRelativePaths }) {
    const workspacePath = useRelativePaths ? activeDoc.workspaceRoot?.path : undefined;
    const reversedHistory = xtabHistory.slice().reverse();
    let tokenBudget = maxTokens;
    let totalTokensConsumed = 0;
    const allDiffs = [];
    // we traverse in reverse (ie from most recent to least recent) because we may terminate early due to token-budget overflow
    for (const entry of reversedHistory) {
        if (allDiffs.length >= nEntries) { // we've reached the maximum number of entries
            break;
        }
        if (entry.kind === 'visibleRanges') {
            continue;
        }
        if (onlyForDocsInPrompt && !docsInPrompt.has(entry.docId)) {
            continue;
        }
        const docDiff = generateDocDiff(entry, workspacePath);
        if (docDiff === null) {
            continue;
        }
        const tokenCount = computeTokens(docDiff);
        tokenBudget -= tokenCount;
        if (tokenBudget < 0) {
            break;
        }
        else {
            totalTokensConsumed += tokenCount;
            allDiffs.push(docDiff);
        }
    }
    const diffsFromOldestToNewest = allDiffs.reverse();
    let promptPiece = diffsFromOldestToNewest.join('\n\n');
    // to preserve old behavior where we always had trailing whitespace
    if (diffsFromOldestToNewest.length > 0) {
        promptPiece += '\n';
    }
    return { promptPiece, nDiffs: allDiffs.length, totalTokens: totalTokensConsumed };
}
function generateDocDiff(entry, workspacePath) {
    const docDiffLines = [];
    const lineEdit = edit_1.RootedEdit.toLineEdit(entry.edit);
    const baseLines = entry.edit.base.getLines();
    // group edits into hunks of adjacent edits (eg if line 3 and line 4 are both edited, they should be in the same hunk, but if line 3 and line 5 are edited, they should be in different hunks)
    for (const lineEditGroup of (0, arrays_1.groupAdjacentBy)(lineEdit.replacements, (left, right) => left.lineRange.endLineNumberExclusive >= right.lineRange.startLineNumber)) {
        const oldLines = [];
        const newLines = [];
        let previousEndLineNumberExclusive = lineEditGroup[0].lineRange.startLineNumber;
        for (const singleLineEdit of lineEditGroup) {
            if (previousEndLineNumberExclusive < singleLineEdit.lineRange.startLineNumber) {
                const unchangedLines = baseLines.slice(previousEndLineNumberExclusive - 1, singleLineEdit.lineRange.startLineNumber - 1);
                (0, arrays_1.pushMany)(oldLines, unchangedLines);
                (0, arrays_1.pushMany)(newLines, unchangedLines);
            }
            const replacedOldLines = baseLines.slice(singleLineEdit.lineRange.startLineNumber - 1, singleLineEdit.lineRange.endLineNumberExclusive - 1);
            (0, arrays_1.pushMany)(oldLines, replacedOldLines);
            (0, arrays_1.pushMany)(newLines, singleLineEdit.newLines);
            previousEndLineNumberExclusive = singleLineEdit.lineRange.endLineNumberExclusive;
        }
        if (oldLines.every(line => line.trim().length === 0) && newLines.every(line => line.trim().length === 0)) {
            // skip over a diff which would only contain -/+ without any content
            continue;
        }
        // skip no-op diffs where the old and new lines are identical
        if (oldLines.length === newLines.length && oldLines.every((line, i) => line === newLines[i])) {
            continue;
        }
        const startLineNumber = lineEditGroup[0].lineRange.startLineNumber - 1;
        docDiffLines.push(`@@ -${startLineNumber},${oldLines.length} +${startLineNumber},${newLines.length} @@`);
        (0, arrays_1.pushMany)(docDiffLines, oldLines.map(x => `-${x}`));
        (0, arrays_1.pushMany)(docDiffLines, newLines.map(x => `+${x}`));
    }
    if (docDiffLines.length === 0) {
        return null;
    }
    const uniquePath = (0, promptCraftingUtils_1.toUniquePath)(entry.docId, workspacePath);
    const docDiffArr = [
        `--- ${uniquePath}`,
        `+++ ${uniquePath}`,
    ];
    (0, arrays_1.pushMany)(docDiffArr, docDiffLines);
    const docDiff = docDiffArr.join('\n');
    return docDiff;
}
//# sourceMappingURL=diffHistoryForPrompt.js.map