"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCrossFieldTargetFromMove = exports.splitMarkForMoveEffects = exports.getMoveIn = exports.isMoveIn = exports.isMoveOut = exports.isMoveMark = exports.getMoveEffect = exports.setMoveEffect = exports.MoveEnd = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const index_js_1 = require("../../util/index.js");
const index_js_2 = require("../modular-schema/index.js");
const utils_js_1 = require("./utils.js");
var MoveEnd;
(function (MoveEnd) {
    MoveEnd[MoveEnd["Source"] = 0] = "Source";
    MoveEnd[MoveEnd["Dest"] = 1] = "Dest";
})(MoveEnd || (exports.MoveEnd = MoveEnd = {}));
function setMoveEffect(moveEffects, target, revision, id, count, effect, invalidate = true) {
    effect.basis = id;
    moveEffects.set(target, revision, id, count, effect, invalidate);
}
exports.setMoveEffect = setMoveEffect;
function getMoveEffect(moveEffects, target, revision, id, count, addDependency = true) {
    const result = moveEffects.get(target, revision, id, count, addDependency);
    return result.value === undefined
        ? result
        : { ...result, value: adjustMoveEffectBasis(result.value, id) };
}
exports.getMoveEffect = getMoveEffect;
function isMoveMark(effect) {
    return isMoveOut(effect) || isMoveIn(effect);
}
exports.isMoveMark = isMoveMark;
function isMoveOut(effect) {
    return effect.type === "MoveOut";
}
exports.isMoveOut = isMoveOut;
function isMoveIn(effect) {
    return effect.type === "MoveIn";
}
exports.isMoveIn = isMoveIn;
function getMoveIn(effect) {
    switch (effect.type) {
        case "MoveIn": {
            return effect;
        }
        case "AttachAndDetach": {
            return getMoveIn(effect.attach);
        }
        default: {
            return undefined;
        }
    }
}
exports.getMoveIn = getMoveIn;
function adjustMoveEffectBasis(effect, newBasis) {
    if (effect.basis === newBasis) {
        return effect;
    }
    const adjusted = { ...effect, basis: newBasis };
    const basisShift = newBasis - effect.basis;
    (0, internal_1.assert)(basisShift > 0, 0x812 /* Expected basis shift to be positive */);
    if (effect.endpoint !== undefined) {
        adjusted.endpoint = adjustChangeAtomId(effect.endpoint, basisShift);
    }
    if (effect.truncatedEndpoint !== undefined) {
        adjusted.truncatedEndpoint = adjustChangeAtomId(effect.truncatedEndpoint, basisShift);
    }
    if (effect.truncatedEndpointForInner !== undefined) {
        adjusted.truncatedEndpointForInner = adjustChangeAtomId(effect.truncatedEndpointForInner, basisShift);
    }
    if (effect.movedEffect !== undefined) {
        const [_mark1, mark2] = (0, utils_js_1.splitMarkEffect)(effect.movedEffect, basisShift);
        adjusted.movedEffect = mark2;
    }
    return adjusted;
}
function splitMarkForMoveEffects(mark, effects) {
    const length = getFirstMoveEffectLength(mark, mark.count, effects);
    return length < mark.count ? (0, utils_js_1.splitMark)(mark, length) : [mark];
}
exports.splitMarkForMoveEffects = splitMarkForMoveEffects;
function getFirstMoveEffectLength(markEffect, count, effects) {
    if (isMoveMark(markEffect)) {
        return getMoveEffect(effects, getCrossFieldTargetFromMove(markEffect), markEffect.revision, markEffect.id, count).length;
    }
    else if ((0, utils_js_1.isAttachAndDetachEffect)(markEffect)) {
        return Math.min(getFirstMoveEffectLength(markEffect.attach, count, effects), getFirstMoveEffectLength(markEffect.detach, count, effects));
    }
    return count;
}
function getCrossFieldTargetFromMove(mark) {
    const type = mark.type;
    switch (type) {
        case "MoveIn": {
            return index_js_2.CrossFieldTarget.Destination;
        }
        case "MoveOut": {
            return index_js_2.CrossFieldTarget.Source;
        }
        default: {
            (0, internal_1.unreachableCase)(type);
        }
    }
}
exports.getCrossFieldTargetFromMove = getCrossFieldTargetFromMove;
function adjustChangeAtomId(id, shift) {
    return {
        ...id,
        localId: (0, index_js_1.brand)(id.localId + shift),
    };
}
//# sourceMappingURL=moveEffectTable.js.map