/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { Type } from "@sinclair/typebox";
import { FieldKindWithEditor, referenceFreeFieldChangeRebaser,
// eslint-disable-next-line import/no-internal-modules
 } from "../../../feature-libraries/modular-schema/index.js";
import { fail } from "../../../util/index.js";
import { makeCodecFamily } from "../../../codec/index.js";
import { makeDetachedNodeId, } from "../../../core/index.js";
import { Multiplicity } from "../../../feature-libraries/index.js";
import { makeValueCodec } from "../../codec/index.js";
/**
 * Picks the last value written.
 *
 * TODO: it seems impossible for this to obey the desired axioms.
 * Specifically inverse needs to cancel, restoring the value from the previous change which was discarded.
 */
export function lastWriteWinsRebaser(data) {
    const compose = (_change1, change2) => change2;
    const rebase = (change, _over) => change;
    return referenceFreeFieldChangeRebaser({ ...data, compose, rebase });
}
/**
 * Picks the last value written.
 *
 * Consistent if used on valid paths with correct old states.
 */
export function replaceRebaser() {
    return referenceFreeFieldChangeRebaser({
        rebase: (change, over) => {
            if (change === 0) {
                return 0;
            }
            if (over === 0) {
                return change;
            }
            return { old: over.new, new: change.new };
        },
        compose: (change1, change2) => {
            if (change1 === 0) {
                return change2;
            }
            else if (change2 === 0) {
                return change1;
            }
            return { old: change1.old, new: change2.new };
        },
        invert: (changes) => {
            return changes === 0 ? 0 : { old: changes.new, new: changes.old };
        },
    });
}
export const valueHandler = {
    rebaser: replaceRebaser(),
    codecsFactory: () => makeCodecFamily([
        [0, makeValueCodec(Type.Any())],
    ]),
    editor: { buildChildChange: (index, change) => fail("Child changes not supported") },
    intoDelta: ({ change, revision }) => {
        const delta = {};
        if (change !== 0) {
            // We use the new and old numbers as the node ids.
            // These would have no real meaning to a delta consumer, but these delta are only used for testing.
            const detach = makeDetachedNodeId(revision, change.old);
            const attach = makeDetachedNodeId(revision, change.new);
            delta.local = [{ count: 1, attach, detach }];
        }
        return delta;
    },
    relevantRemovedRoots: (change) => [],
    isEmpty: (change) => change === 0,
    createEmpty: () => 0,
};
export const valueField = new FieldKindWithEditor("Value", Multiplicity.Single, valueHandler, (a, b) => false, new Set());
//# sourceMappingURL=basicRebasers.js.map