"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, replacer) {
    const updatedMarks = new markListFactory_js_1.MarkListFactory();
    for (const mark of changeset) {
        const updatedMark = updateMark(mark, replacer);
        updatedMarks.push(updatedMark);
    }
    return updatedMarks.list;
}
exports.replaceRevisions = replaceRevisions;
function updateMark(mark, replacer) {
    const updatedMark = { ...updateEffect(mark, mark.count, replacer) };
    if (mark.cellId !== undefined) {
        updatedMark.cellId = replacer.getUpdatedAtomId(mark.cellId, mark.count);
    }
    if (mark.changes !== undefined) {
        updatedMark.changes = replacer.getUpdatedAtomId(mark.changes);
    }
    return updatedMark;
}
function updateEffect(input, count, replacer) {
    const mark = (0, utils_js_1.isDetach)(input) || (0, utils_js_1.isRename)(input) ? updateIdOverride(input, count, replacer) : input;
    const type = mark.type;
    switch (type) {
        case "Rename":
        case types_js_1.NoopMarkType: {
            return mark;
        }
        case "AttachAndDetach": {
            return {
                ...mark,
                attach: updateEffect(mark.attach, count, replacer),
                detach: updateEffect(mark.detach, count, replacer),
            };
        }
        case "MoveIn":
        case "MoveOut": {
            return updateMoveEffect(
            // For some reason, TypeScript is not able to infer that `mark` cannot be a `NoopMark` here.
            mark, count, replacer);
        }
        case "Insert":
        case "Remove": {
            return updateRevisionAndId(mark, count, replacer);
        }
        default: {
            (0, internal_1.unreachableCase)(type);
        }
    }
}
function updateIdOverride(effect, count, replacer) {
    if (effect.idOverride === undefined) {
        return effect;
    }
    const idOverride = replacer.getUpdatedAtomId(effect.idOverride, count);
    return { ...effect, idOverride };
}
function updateMoveEffect(effect, count, replacer) {
    return effect.finalEndpoint === undefined
        ? updateRevisionAndId(effect, count, replacer)
        : updateRevisionAndId({
            ...effect,
            finalEndpoint: replacer.getUpdatedAtomId(effect.finalEndpoint, count),
        }, count, replacer);
}
function updateRevisionAndId(input, count, replacer) {
    if (!replacer.isObsolete(input.revision)) {
        return input;
    }
    const newAtom = replacer.getUpdatedAtomId((0, index_js_1.makeChangeAtomId)(input.id, input.revision), count);
    return withRevisionAndId(input, newAtom.revision, newAtom.localId);
}
function withRevisionAndId(input, revision, id) {
    const updated = { ...input, revision, id };
    if (revision === undefined) {
        delete updated.revision;
    }
    return updated;
}
//# sourceMappingURL=replaceRevisions.js.map