/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { assert } from "@fluidframework/core-utils/internal";
import { MarkListFactory } from "./markListFactory.js";
import { splitMark } from "./utils.js";
export const sequenceFieldEditor = {
    buildChildChange: (index, change) => markAtIndex(index, { count: 1, changes: change }),
    insert: (index, count, firstId, revision) => {
        const mark = {
            type: "Insert",
            id: firstId.localId,
            count,
            cellId: firstId,
            revision,
        };
        return markAtIndex(index, mark);
    },
    remove: (index, count, id, revision) => count === 0 ? [] : markAtIndex(index, { type: "Remove", count, id, revision }),
    revive: (index, count, detachEvent, revision) => {
        assert(detachEvent.revision !== undefined, 0x724 /* Detach event must have a revision */);
        const mark = {
            type: "Insert",
            id: detachEvent.localId,
            count,
            cellId: detachEvent,
            revision,
        };
        return count === 0 ? [] : markAtIndex(index, mark);
    },
    move(sourceIndex, count, destIndex, detachCellId, attachCellId, revision) {
        const moveIn = {
            type: "MoveIn",
            id: detachCellId,
            count,
            cellId: attachCellId,
            revision,
        };
        const moveOut = {
            type: "MoveOut",
            id: detachCellId,
            count,
            revision,
        };
        return moveMarksToMarkList(sourceIndex, count, destIndex, moveOut, moveIn);
    },
    moveOut(sourceIndex, count, detachCellId, revision) {
        const moveOut = {
            type: "MoveOut",
            id: detachCellId,
            count,
            revision,
        };
        return markAtIndex(sourceIndex, moveOut);
    },
    moveIn(destIndex, count, moveId, attachCellId, revision) {
        const moveIn = {
            type: "MoveIn",
            id: moveId,
            count,
            cellId: attachCellId,
            revision,
        };
        return markAtIndex(destIndex, moveIn);
    },
    return(sourceIndex, count, destIndex, detachCellId, attachCellId, revision) {
        const moveOut = {
            type: "MoveOut",
            id: attachCellId.localId,
            idOverride: detachCellId,
            count,
            revision,
        };
        const returnTo = {
            type: "MoveIn",
            id: attachCellId.localId,
            count,
            cellId: attachCellId,
            revision,
        };
        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();
    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] = 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