var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
const VEGA_LITE_FENCE_START = "```vega-lite";
const FENCE_END = "```";
export class VegaLiteStreamBuffer {
    constructor() {
        this.bufferedTextDelta = "";
        this.isRenderingVegaLite = false;
    }
    push(textDelta, emit) {
        return __awaiter(this, void 0, void 0, function* () {
            this.bufferedTextDelta += textDelta;
            if (hasUnclosedLatestVegaLiteBlock(this.bufferedTextDelta)) {
                if (!this.isRenderingVegaLite) {
                    this.isRenderingVegaLite = true;
                    yield (emit === null || emit === void 0 ? void 0 : emit({
                        type: "rendering",
                        phase: "start",
                        label: "Rendering...",
                    }));
                }
                return;
            }
            if (this.isRenderingVegaLite) {
                this.isRenderingVegaLite = false;
                yield (emit === null || emit === void 0 ? void 0 : emit({
                    type: "rendering",
                    phase: "end",
                    label: "Rendering...",
                }));
            }
            const streamableLength = this.bufferedTextDelta.includes(VEGA_LITE_FENCE_START)
                ? this.bufferedTextDelta.length
                : this.bufferedTextDelta.length - getPartialVegaLiteFenceStartLength(this.bufferedTextDelta);
            if (!streamableLength) {
                return;
            }
            yield (emit === null || emit === void 0 ? void 0 : emit({
                type: "text-delta",
                delta: this.bufferedTextDelta.slice(0, streamableLength),
            }));
            this.bufferedTextDelta = this.bufferedTextDelta.slice(streamableLength);
        });
    }
    flush(emit) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.isRenderingVegaLite) {
                yield (emit === null || emit === void 0 ? void 0 : emit({
                    type: "rendering",
                    phase: "end",
                    label: "Rendering...",
                }));
                this.isRenderingVegaLite = false;
            }
            if (this.bufferedTextDelta) {
                yield (emit === null || emit === void 0 ? void 0 : emit({
                    type: "text-delta",
                    delta: this.bufferedTextDelta,
                }));
                this.bufferedTextDelta = "";
            }
        });
    }
}
function hasUnclosedLatestVegaLiteBlock(text) {
    const latestBlockStart = text.lastIndexOf(VEGA_LITE_FENCE_START);
    if (latestBlockStart === -1) {
        return false;
    }
    const blockContentStart = latestBlockStart + VEGA_LITE_FENCE_START.length;
    return text.indexOf(FENCE_END, blockContentStart) === -1;
}
function getPartialVegaLiteFenceStartLength(text) {
    for (let length = Math.min(text.length, VEGA_LITE_FENCE_START.length - 1); length > 0; length -= 1) {
        if (VEGA_LITE_FENCE_START.startsWith(text.slice(-length))) {
            return length;
        }
    }
    return 0;
}
