"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.sequenceFieldEditor = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const index_js_1 = require("../../util/index.js");
const markListFactory_js_1 = require("./markListFactory.js");
const utils_js_1 = require("./utils.js");
exports.sequenceFieldEditor = {
    buildChildChange: (index, change) => markAtIndex(index, { count: 1, changes: change }),
    insert: (index, count, firstId) => {
        const mark = {
            type: "Insert",
            id: firstId,
            count,
            cellId: { localId: firstId },
        };
        return markAtIndex(index, mark);
    },
    remove: (index, count, id) => count === 0 ? [] : markAtIndex(index, { type: "Remove", count, id }),
    revive: (index, count, detachEvent) => {
        (0, internal_1.assert)(detachEvent.revision !== undefined, 0x724 /* Detach event must have a revision */);
        const mark = {
            type: "Insert",
            id: detachEvent.localId,
            count,
            cellId: detachEvent,
        };
        return count === 0 ? [] : markAtIndex(index, mark);
    },
    move(sourceIndex, count, destIndex, id) {
        const moveIn = {
            type: "MoveIn",
            id,
            count,
            cellId: { localId: id },
        };
        const moveOut = {
            type: "MoveOut",
            id,
            count,
        };
        return moveMarksToMarkList(sourceIndex, count, destIndex, moveOut, moveIn);
    },
    moveOut(sourceIndex, count, id) {
        const moveOut = {
            type: "MoveOut",
            id,
            count,
        };
        return markAtIndex(sourceIndex, moveOut);
    },
    moveIn(destIndex, count, id) {
        const moveIn = {
            type: "MoveIn",
            id,
            count,
            cellId: { localId: id },
        };
        return markAtIndex(destIndex, moveIn);
    },
    return(sourceIndex, count, destIndex, detachEvent) {
        const id = (0, index_js_1.brand)(0);
        const moveOut = {
            type: "MoveOut",
            id,
            count,
        };
        const returnTo = {
            type: "MoveIn",
            id,
            count,
            cellId: detachEvent,
        };
        return moveMarksToMarkList(sourceIndex, count, destIndex, moveOut, returnTo);
    },
};
function moveMarksToMarkList(sourceIndex, count, destIndex, detach, attach) {
    if (count === 0) {
        return [];
    }
    const firstIndexBeyondMoveOut = sourceIndex + count;
    const marks = new markListFactory_js_1.MarkListFactory();
    marks.pushOffset(Math.min(sourceIndex, destIndex));
    if (destIndex <= sourceIndex) {
        // The destination is fully before the source
        marks.pushContent(attach);
        marks.pushOffset(sourceIndex - destIndex);
        marks.pushContent(detach);
    }
    else if (firstIndexBeyondMoveOut <= destIndex) {
        // The destination is fully after the source
        marks.pushContent(detach);
        marks.pushOffset(destIndex - firstIndexBeyondMoveOut);
        marks.pushContent(attach);
    }
    else {
        const firstSectionLength = destIndex - sourceIndex;
        // The destination is in the middle of the source
        const [detach1, detach2] = (0, utils_js_1.splitMark)(detach, firstSectionLength);
        marks.pushContent(detach1);
        marks.pushContent(attach);
        marks.pushContent(detach2);
    }
    return marks.list;
}
function markAtIndex(index, mark) {
    return index === 0 ? [mark] : [{ count: index }, mark];
}
//# sourceMappingURL=sequenceFieldEditor.js.map