"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarkQueue = void 0;
const core_utils_1 = require("@fluidframework/core-utils");
const moveEffectTable_1 = require("./moveEffectTable");
const utils_1 = require("./utils");
class MarkQueue {
    constructor(list, revision, moveEffects, consumeEffects, genId, composeChanges) {
        this.list = list;
        this.revision = revision;
        this.moveEffects = moveEffects;
        this.consumeEffects = consumeEffects;
        this.genId = genId;
        this.composeChanges = composeChanges;
        this.stack = [];
        this.index = 0;
        this.list = list;
    }
    isEmpty() {
        return this.peek() === undefined;
    }
    dequeue() {
        const output = this.tryDequeue();
        (0, core_utils_1.assert)(output !== undefined, 0x4e2 /* Unexpected end of mark queue */);
        return output;
    }
    tryDequeue() {
        if (this.stack.length > 0) {
            return this.stack.pop();
        }
        else if (this.index < this.list.length) {
            const mark = this.list[this.index++];
            if (mark === undefined) {
                return undefined;
            }
            const splitMarks = (0, moveEffectTable_1.applyMoveEffectsToMark)(mark, this.revision, this.moveEffects, this.consumeEffects, this.composeChanges);
            if (splitMarks.length === 0) {
                return undefined;
            }
            const result = splitMarks[0];
            for (let i = splitMarks.length - 1; i > 0; i--) {
                this.stack.push(splitMarks[i]);
            }
            return result;
        }
    }
    /**
     * Dequeues the first `length` sized portion of the next mark.
     * The caller must verify that the next mark (as returned by peek) is longer than this length.
     * @param length - The length to dequeue, measured in the input context.
     */
    dequeueUpTo(length) {
        const mark = this.dequeue();
        if (mark.count <= length) {
            return mark;
        }
        const [mark1, mark2] = (0, utils_1.splitMark)(mark, length);
        this.stack.push(mark2);
        return mark1;
    }
    peek() {
        const mark = this.tryDequeue();
        if (mark !== undefined) {
            this.stack.push(mark);
        }
        return mark;
    }
}
exports.MarkQueue = MarkQueue;
//# sourceMappingURL=markQueue.js.map