"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.ResponseParseResult = void 0;
exports.handleEditWindowOnly = handleEditWindowOnly;
exports.handleCodeBlock = handleCodeBlock;
exports.handleEditWindowWithEditIntent = handleEditWindowWithEditIntent;
exports.handleUnifiedWithXml = handleUnifiedWithXml;
const statelessNextEditProvider_1 = require("../../../platform/inlineEdits/common/statelessNextEditProvider");
const lineEdit_1 = require("../../../util/vs/editor/common/core/edits/lineEdit");
const lineRange_1 = require("../../../util/vs/editor/common/core/ranges/lineRange");
const tags_1 = require("../common/tags");
const editIntent_1 = require("./editIntent");
const xtabUtils_1 = require("./xtabUtils");
// ============================================================================
// Result type
// ============================================================================
var ResponseParseResult;
(function (ResponseParseResult) {
    /**
     * The response contains edit-window lines to be fed into *ResponseProcessor.diff*.
     */
    class EditWindowLines {
        constructor(lines, editIntentMetadata) {
            this.lines = lines;
            this.editIntentMetadata = editIntentMetadata;
        }
    }
    ResponseParseResult.EditWindowLines = EditWindowLines;
    /**
     * The handler has finished — no more processing needed. Carries a {@link NoNextEditReason}.
     */
    class Done {
        constructor(reason) {
            this.reason = reason;
        }
    }
    ResponseParseResult.Done = Done;
    /**
     * The handler yields edits directly (e.g. INSERT or CustomDiffPatch).
     * The coordinator should `yield*` the stream.
     */
    class DirectEdits {
        constructor(stream) {
            this.stream = stream;
        }
    }
    ResponseParseResult.DirectEdits = DirectEdits;
})(ResponseParseResult || (exports.ResponseParseResult = ResponseParseResult = {}));
// ============================================================================
// Handler: EditWindowOnly
// ============================================================================
function handleEditWindowOnly(linesStream) {
    return new ResponseParseResult.EditWindowLines(linesStream);
}
// ============================================================================
// Handler: CodeBlock
// ============================================================================
function handleCodeBlock(linesStream) {
    return new ResponseParseResult.EditWindowLines((0, xtabUtils_1.linesWithBackticksRemoved)(linesStream));
}
// ============================================================================
// Handler: EditWindowWithEditIntent / EditWindowWithEditIntentShort
// ============================================================================
async function handleEditWindowWithEditIntent(linesStream, tracer, parseMode) {
    const { editIntent, remainingLinesStream, parseError } = await (0, editIntent_1.parseEditIntentFromStream)(linesStream, tracer, parseMode);
    return new ResponseParseResult.EditWindowLines(remainingLinesStream, { intent: editIntent, parseError });
}
async function handleUnifiedWithXml(linesStream, ctx, documentBeforeEdits, tracer) {
    const linesIter = linesStream[Symbol.asyncIterator]();
    const firstLine = await linesIter.next();
    if (firstLine.done) {
        return new ResponseParseResult.Done(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(documentBeforeEdits, ctx.editWindow));
    }
    const trimmedFirstLine = firstLine.value.trim();
    if (trimmedFirstLine === tags_1.ResponseTags.NO_CHANGE.start) {
        return new ResponseParseResult.Done(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(documentBeforeEdits, ctx.editWindow));
    }
    if (trimmedFirstLine === tags_1.ResponseTags.INSERT.start) {
        return new ResponseParseResult.DirectEdits(generateInsertEdits(linesIter, ctx, documentBeforeEdits));
    }
    if (trimmedFirstLine === tags_1.ResponseTags.EDIT.start) {
        const editLines = generateEditLines(linesIter);
        return new ResponseParseResult.EditWindowLines(editLines);
    }
    return new ResponseParseResult.Done(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(new Error(`unexpected tag ${trimmedFirstLine}`)));
}
// ============================================================================
// Internal generators for UnifiedWithXml sub-tags
// ============================================================================
async function* generateInsertEdits(linesIter, ctx, documentBeforeEdits) {
    const { editWindowLines, editWindowLineRange, cursorOriginalLinesOffset, cursorColumnZeroBased, editWindow, originalEditWindow, targetDocument, isFromCursorJump } = ctx;
    const lineWithCursorContinued = await linesIter.next();
    if (lineWithCursorContinued.done || lineWithCursorContinued.value.includes(tags_1.ResponseTags.INSERT.end)) {
        return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(documentBeforeEdits, editWindow);
    }
    const cursorLineContent = editWindowLines[cursorOriginalLinesOffset];
    const edit = new lineEdit_1.LineReplacement(new lineRange_1.LineRange(editWindowLineRange.start + cursorOriginalLinesOffset + 1 /* 0-based to 1-based */, editWindowLineRange.start + cursorOriginalLinesOffset + 2), [cursorLineContent.slice(0, cursorColumnZeroBased) + lineWithCursorContinued.value + cursorLineContent.slice(cursorColumnZeroBased)]);
    yield { edit, isFromCursorJump, window: editWindow, originalWindow: originalEditWindow, targetDocument };
    const lines = [];
    let v = await linesIter.next();
    while (!v.done) {
        if (v.value.includes(tags_1.ResponseTags.INSERT.end)) {
            break;
        }
        else {
            lines.push(v.value);
        }
        v = await linesIter.next();
    }
    const line = editWindowLineRange.start + cursorOriginalLinesOffset + 2;
    yield {
        edit: new lineEdit_1.LineReplacement(new lineRange_1.LineRange(line, line), lines),
        isFromCursorJump,
        window: editWindow,
        originalWindow: originalEditWindow,
        targetDocument,
    };
    return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(documentBeforeEdits, editWindow);
}
async function* generateEditLines(linesIter) {
    let v = await linesIter.next();
    while (!v.done) {
        if (v.value.includes(tags_1.ResponseTags.EDIT.end)) {
            return;
        }
        yield v.value;
        v = await linesIter.next();
    }
}
//# sourceMappingURL=responseFormatHandlers.js.map