/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { Type } from "@sinclair/typebox";
import { makeCodecFamily, makeVersionDispatchingCodec, withSchemaValidation, } from "../codec/index.js";
import { Message } from "./messageFormat.js";
export function makeMessageCodec(changeCodecs, revisionTagCodec, options, writeVersion) {
    const family = makeMessageCodecs(changeCodecs, revisionTagCodec, options);
    return makeVersionDispatchingCodec(family, { ...options, writeVersion });
}
/**
 * @privateRemarks - Exported for testing.
 */
export function makeMessageCodecs(changeCodecs, revisionTagCodec, options) {
    const v1Codec = makeV1CodecWithVersion(changeCodecs.resolve(1).json, revisionTagCodec, options, 1);
    return makeCodecFamily([
        // Back-compat: messages weren't always written with an explicit version field.
        [undefined, v1Codec],
        [1, v1Codec],
        [2, makeV1CodecWithVersion(changeCodecs.resolve(2).json, revisionTagCodec, options, 2)],
        [3, makeV1CodecWithVersion(changeCodecs.resolve(3).json, revisionTagCodec, options, 3)],
        [4, makeV1CodecWithVersion(changeCodecs.resolve(4).json, revisionTagCodec, options, 4)],
    ]);
}
function makeV1CodecWithVersion(changeCodec, revisionTagCodec, options, version) {
    return withSchemaValidation(Message(changeCodec.encodedSchema ?? Type.Any()), {
        encode: ({ commit, sessionId: originatorId }, context) => {
            const message = {
                revision: revisionTagCodec.encode(commit.revision, {
                    originatorId,
                    idCompressor: context.idCompressor,
                    revision: undefined,
                }),
                originatorId,
                changeset: changeCodec.encode(commit.change, {
                    originatorId,
                    schema: context.schema,
                    idCompressor: context.idCompressor,
                    revision: commit.revision,
                }),
                version,
            };
            return message;
        },
        decode: (encoded, context) => {
            const { revision: encodedRevision, originatorId, changeset, } = encoded;
            const revision = revisionTagCodec.decode(encodedRevision, {
                originatorId,
                revision: undefined,
                idCompressor: context.idCompressor,
            });
            return {
                commit: {
                    revision,
                    change: changeCodec.decode(changeset, {
                        originatorId,
                        revision,
                        idCompressor: context.idCompressor,
                    }),
                },
                sessionId: originatorId,
            };
        },
    }, options.jsonValidator);
}
//# sourceMappingURL=messageCodecs.js.map