/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { makeChangeAtomIdCodec } from "../changeAtomIdCodec.js";
import { EncodedNodeChangeset } from "../modular-schema/index.js";
import { EncodedOptionalChangeset, EncodedRegisterId } from "./optionalFieldChangeFormatV2.js";
function makeRegisterIdCodec(changeAtomIdCodec) {
    return {
        encode: (registerId, context) => {
            if (registerId === "self") {
                return null;
            }
            return changeAtomIdCodec.encode(registerId, context);
        },
        decode: (registerId, context) => {
            if (registerId === null) {
                return "self";
            }
            return changeAtomIdCodec.decode(registerId, context);
        },
        encodedSchema: EncodedRegisterId,
    };
}
export function makeOptionalFieldCodec(revisionTagCodec) {
    const changeAtomIdCodec = makeChangeAtomIdCodec(revisionTagCodec);
    const registerIdCodec = makeRegisterIdCodec(changeAtomIdCodec);
    return {
        encode: (change, context) => {
            const encoded = {};
            if (change.moves.length > 0) {
                encoded.m = change.moves.map(([src, dst]) => [
                    changeAtomIdCodec.encode(src, context.baseContext),
                    changeAtomIdCodec.encode(dst, context.baseContext),
                ]);
            }
            if (change.valueReplace !== undefined) {
                encoded.r = {
                    e: change.valueReplace.isEmpty,
                    d: changeAtomIdCodec.encode(change.valueReplace.dst, context.baseContext),
                };
                if (change.valueReplace.src !== undefined) {
                    encoded.r.s = registerIdCodec.encode(change.valueReplace.src, context.baseContext);
                }
            }
            if (change.childChanges.length > 0) {
                encoded.c = [];
                for (const [id, childChange] of change.childChanges) {
                    encoded.c.push([
                        registerIdCodec.encode(id, context.baseContext),
                        context.encodeNode(childChange),
                    ]);
                }
            }
            return encoded;
        },
        decode: (encoded, context) => {
            const decoded = {
                moves: encoded.m?.map(([encodedSrc, encodedDst]) => [
                    changeAtomIdCodec.decode(encodedSrc, context.baseContext),
                    changeAtomIdCodec.decode(encodedDst, context.baseContext),
                ]) ?? [],
                childChanges: encoded.c?.map(([id, encodedChange]) => [
                    registerIdCodec.decode(id, context.baseContext),
                    context.decodeNode(encodedChange),
                ]) ?? [],
            };
            if (encoded.r !== undefined) {
                const replace = {
                    isEmpty: encoded.r.e,
                    dst: changeAtomIdCodec.decode(encoded.r.d, context.baseContext),
                };
                if (encoded.r.s !== undefined) {
                    replace.src = registerIdCodec.decode(encoded.r.s, context.baseContext);
                }
                decoded.valueReplace = replace;
            }
            return decoded;
        },
        encodedSchema: EncodedOptionalChangeset(EncodedNodeChangeset),
    };
}
//# sourceMappingURL=optionalFieldCodecV2.js.map