"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.replaceRevisions = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const index_js_1 = require("../../core/index.js");
const markListFactory_js_1 = require("./markListFactory.js");
const types_js_1 = require("./types.js");
const utils_js_1 = require("./utils.js");
function replaceRevisions(changeset, revisionsToReplace, newRevision) {
    const updatedMarks = new markListFactory_js_1.MarkListFactory();
    for (const mark of changeset) {
        const updatedMark = updateMark(mark, revisionsToReplace, newRevision);
        updatedMarks.push(updatedMark);
    }
    return updatedMarks.list;
}
exports.replaceRevisions = replaceRevisions;
function updateMark(mark, revisionsToReplace, newRevision) {
    const updatedMark = { ...updateEffect(mark, revisionsToReplace, newRevision) };
    if (mark.cellId !== undefined) {
        updatedMark.cellId = (0, index_js_1.replaceAtomRevisions)(mark.cellId, revisionsToReplace, newRevision);
    }
    if (mark.changes !== undefined) {
        updatedMark.changes = (0, index_js_1.replaceAtomRevisions)(mark.changes, revisionsToReplace, newRevision);
    }
    return updatedMark;
}
function updateEffect(input, revisionsToReplace, newRevision) {
    const mark = (0, utils_js_1.isDetach)(input) || (0, utils_js_1.isRename)(input)
        ? updateIdOverride(input, revisionsToReplace, newRevision)
        : input;
    const type = mark.type;
    switch (type) {
        case "Rename":
        case types_js_1.NoopMarkType:
            return mark;
        case "AttachAndDetach":
            return {
                ...mark,
                attach: updateEffect(mark.attach, revisionsToReplace, newRevision),
                detach: updateEffect(mark.detach, revisionsToReplace, newRevision),
            };
        case "MoveIn":
        case "MoveOut":
            return updateMoveEffect(
            // For some reason, TypeScript is not able to infer that `mark` cannot be a `NoopMark` here.
            mark, revisionsToReplace, newRevision);
        case "Insert":
        case "Remove":
            return updateRevision(mark, revisionsToReplace, newRevision);
        default:
            (0, internal_1.unreachableCase)(type);
    }
}
function updateIdOverride(effect, revisionsToReplace, newRevision) {
    if (effect.idOverride !== undefined) {
        const idOverride = (0, index_js_1.replaceAtomRevisions)(effect.idOverride, revisionsToReplace, newRevision);
        return { ...effect, idOverride };
    }
    else {
        return effect;
    }
}
function updateMoveEffect(effect, revisionsToReplace, newRevision) {
    return effect.finalEndpoint !== undefined
        ? updateRevision({
            ...effect,
            finalEndpoint: updateRevision(effect.finalEndpoint, revisionsToReplace, newRevision),
        }, revisionsToReplace, newRevision)
        : updateRevision(effect, revisionsToReplace, newRevision);
}
function updateRevision(input, revisionsToReplace, newRevision) {
    return revisionsToReplace.has(input.revision) ? withRevision(input, newRevision) : input;
}
function withRevision(input, revision) {
    const updated = { ...input, revision };
    if (revision === undefined) {
        delete updated.revision;
    }
    return updated;
}
//# sourceMappingURL=replaceRevisions.js.map