/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { Type } from "@sinclair/typebox";
import { makeCodecFamily, unitCodec } from "../../codec";
import { makeChangeAtomIdCodec } from "../changeAtomIdCodec";
import { EncodedOptionalChangeset, EncodedRegisterId } from "./optionalFieldChangeFormat";
export const noChangeCodecFamily = makeCodecFamily([
    [0, unitCodec],
]);
export const makeOptionalFieldCodecFamily = (childCodec, revisionTagCodec) => makeCodecFamily([[0, makeOptionalFieldCodec(childCodec, revisionTagCodec)]]);
function makeRegisterIdCodec(revisionTagCodec) {
    const changeAtomIdCodec = makeChangeAtomIdCodec(revisionTagCodec);
    return {
        encode: (registerId, originatorId) => {
            if (registerId === "self") {
                return null;
            }
            return changeAtomIdCodec.encode(registerId, originatorId);
        },
        decode: (registerId, originatorId) => {
            if (registerId === null) {
                return "self";
            }
            return changeAtomIdCodec.decode(registerId, originatorId);
        },
        encodedSchema: EncodedRegisterId,
    };
}
function makeOptionalFieldCodec(childCodec, revisionTagCodec) {
    const registerIdCodec = makeRegisterIdCodec(revisionTagCodec);
    return {
        encode: (change, originatorId) => {
            const encoded = {};
            if (change.moves.length > 0) {
                encoded.m = [];
                for (const [src, dst, type] of change.moves) {
                    encoded.m.push([
                        registerIdCodec.encode(src, originatorId),
                        registerIdCodec.encode(dst, originatorId),
                        type === "nodeTargeting",
                    ]);
                }
            }
            if (change.childChanges.length > 0) {
                encoded.c = [];
                for (const [id, childChange] of change.childChanges) {
                    encoded.c.push([
                        registerIdCodec.encode(id, originatorId),
                        childCodec.encode(childChange, originatorId),
                    ]);
                }
            }
            if (change.reservedDetachId !== undefined) {
                encoded.d = registerIdCodec.encode(change.reservedDetachId, originatorId);
            }
            return encoded;
        },
        decode: (encoded, originatorId) => {
            const moves = encoded.m?.map(([src, dst, type]) => [
                registerIdCodec.decode(src, originatorId),
                registerIdCodec.decode(dst, originatorId),
                type ? "nodeTargeting" : "cellTargeting",
            ]) ?? [];
            const decoded = {
                moves,
                childChanges: encoded.c?.map(([id, encodedChange]) => [
                    registerIdCodec.decode(id, originatorId),
                    childCodec.decode(encodedChange, originatorId),
                ]) ?? [],
            };
            if (encoded.d !== undefined) {
                decoded.reservedDetachId = registerIdCodec.decode(encoded.d, originatorId);
            }
            return decoded;
        },
        encodedSchema: EncodedOptionalChangeset(childCodec.encodedSchema ?? Type.Any()),
    };
}
//# sourceMappingURL=optionalFieldCodecs.js.map