/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { emptyDelta, } from "../../../core/index.js";
import { TestChange, testChangeFamilyFactory, asDelta, } from "../../testChange.js";
import { EditManager } from "../../../shared-tree-core/index.js";
import { brand, makeArray } from "../../../util/index.js";
import { mintRevisionTag, testIdCompressor } from "../../utils.js";
export function testChangeEditManagerFactory(options) {
    const family = testChangeFamilyFactory(options.rebaser);
    const manager = editManagerFactory(family, {
        sessionId: options.sessionId,
        autoDiscardRevertibles: options.autoDiscardRevertibles,
    });
    return { manager, family };
}
export function editManagerFactory(family, options = {}) {
    const autoDiscardRevertibles = options.autoDiscardRevertibles ?? true;
    const genId = () => testIdCompressor.generateCompressedId();
    const manager = new EditManager(family, options.sessionId ?? "0", genId);
    if (autoDiscardRevertibles === true) {
        // by default, discard revertibles in the edit manager tests
        manager.localBranch.on("newRevertible", (revertible) => {
            revertible.discard();
        });
    }
    return manager;
}
export function rebaseLocalEditsOverTrunkEdits(localEditCount, trunkEditCount, manager, mintChange, defer = false) {
    // Subscribe to the local branch to emulate the behavior of SharedTree
    manager.localBranch.on("afterChange", ({ change }) => { });
    for (let iChange = 0; iChange < localEditCount; iChange++) {
        manager.localBranch.apply(mintChange(), mintRevisionTag());
    }
    const trunkEdits = makeArray(trunkEditCount, () => ({
        change: mintChange(),
        revision: mintRevisionTag(),
        sessionId: "trunk",
    }));
    const run = () => {
        for (let iChange = 0; iChange < trunkEditCount; iChange++) {
            manager.addSequencedChange(trunkEdits[iChange], brand(iChange + 1), brand(iChange));
        }
    };
    return defer ? run : run();
}
export function rebasePeerEditsOverTrunkEdits(peerEditCount, trunkEditCount, manager, mintChange, defer = false) {
    // Subscribe to the local branch to emulate the behavior of SharedTree
    manager.localBranch.on("afterChange", ({ change }) => { });
    for (let iChange = 0; iChange < trunkEditCount; iChange++) {
        manager.addSequencedChange({
            change: mintChange(),
            revision: mintRevisionTag(),
            sessionId: "trunk",
        }, brand(iChange + 1), brand(iChange));
    }
    const peerEdits = makeArray(peerEditCount, () => ({
        change: mintChange(),
        revision: mintRevisionTag(),
        sessionId: "peer",
    }));
    const run = () => {
        for (let iChange = 0; iChange < peerEditCount; iChange++) {
            manager.addSequencedChange(peerEdits[iChange], brand(iChange + trunkEditCount + 1), brand(0));
        }
    };
    return defer ? run : run();
}
export function rebaseAdvancingPeerEditsOverTrunkEdits(editCount, manager, mintChange, defer = false) {
    // Subscribe to the local branch to emulate the behavior of SharedTree
    manager.localBranch.on("afterChange", ({ change }) => { });
    for (let iChange = 0; iChange < editCount; iChange++) {
        manager.addSequencedChange({
            change: mintChange(),
            revision: mintRevisionTag(),
            sessionId: "trunk",
        }, brand(iChange + 1), brand(iChange));
    }
    const peerEdits = makeArray(editCount, () => ({
        change: mintChange(),
        revision: mintRevisionTag(),
        sessionId: "peer",
    }));
    const run = () => {
        for (let iChange = 0; iChange < editCount; iChange++) {
            manager.addSequencedChange(peerEdits[iChange], brand(iChange + editCount + 1), brand(iChange));
        }
    };
    return defer ? run : run();
}
export function rebaseConcurrentPeerEdits(peerCount, editsPerPeerCount, manager, mintChange, defer = false) {
    // Subscribe to the local branch to emulate the behavior of SharedTree
    manager.localBranch.on("afterChange", ({ change }) => { });
    const peerEdits = [];
    for (let iChange = 0; iChange < editsPerPeerCount; iChange++) {
        for (let iPeer = 0; iPeer < peerCount; iPeer++) {
            peerEdits.push({
                change: mintChange(),
                revision: mintRevisionTag(),
                sessionId: `p${iPeer}`,
            });
        }
    }
    const run = () => {
        for (let iChange = 0; iChange < peerEdits.length; iChange++) {
            manager.addSequencedChange(peerEdits[iChange], brand(iChange + 1), brand(0));
        }
    };
    return defer ? run : run();
}
export function checkChangeList(manager, intentions) {
    TestChange.checkChangeList(getAllChanges(manager), intentions);
}
export function getAllChanges(manager) {
    return manager.getTrunkChanges().concat(manager.getLocalChanges());
}
/** Adds a sequenced change to an `EditManager` and returns the delta that was caused by the change */
export function addSequencedChange(editManager, ...args) {
    let delta = emptyDelta;
    const offChange = editManager.localBranch.on("afterChange", ({ change }) => {
        if (change !== undefined) {
            delta = asDelta(change.change.intentions);
        }
    });
    editManager.addSequencedChange(...args);
    offChange();
    return delta;
}
//# sourceMappingURL=editManagerTestUtils.js.map