/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { makeCodecFamily, withSchemaValidation, } from "../codec/index.js";
import { makeVersionDispatchingCodec } from "../codec/index.js";
import { JsonCompatibleReadOnlySchema, mapIterable, } from "../util/index.js";
import { EncodedEditManager, } from "./editManagerFormat.js";
export function makeEditManagerCodec(changeCodecs, revisionTagCodec, options, writeVersion) {
    const family = makeEditManagerCodecs(changeCodecs, revisionTagCodec, options);
    return makeVersionDispatchingCodec(family, { ...options, writeVersion });
}
export function makeEditManagerCodecs(changeCodecs, revisionTagCodec, options) {
    return makeCodecFamily([
        [1, makeV1CodecWithVersion(changeCodecs.resolve(1), revisionTagCodec, options, 1)],
        [2, makeV1CodecWithVersion(changeCodecs.resolve(2), revisionTagCodec, options, 2)],
        [3, makeV1CodecWithVersion(changeCodecs.resolve(3), revisionTagCodec, options, 3)],
    ]);
}
function makeV1CodecWithVersion(changeCodec, revisionTagCodec, options, version) {
    const format = EncodedEditManager(changeCodec.json.encodedSchema ?? JsonCompatibleReadOnlySchema);
    const encodeCommit = (commit, context) => ({
        ...commit,
        revision: revisionTagCodec.encode(commit.revision, {
            originatorId: commit.sessionId,
            idCompressor: context.idCompressor,
            revision: undefined,
        }),
        change: changeCodec.json.encode(commit.change, { ...context, revision: commit.revision }),
    });
    const decodeCommit = (commit, context) => {
        const revision = revisionTagCodec.decode(commit.revision, {
            originatorId: commit.sessionId,
            idCompressor: context.idCompressor,
            revision: undefined,
        });
        return {
            ...commit,
            revision,
            change: changeCodec.json.decode(commit.change, { ...context, revision }),
        };
    };
    const codec = withSchemaValidation(format, {
        encode: (data, context) => {
            const json = {
                trunk: data.trunk.map((commit) => encodeCommit(commit, {
                    originatorId: commit.sessionId,
                    idCompressor: context.idCompressor,
                    schema: context.schema,
                    revision: undefined,
                })),
                branches: Array.from(data.peerLocalBranches.entries(), ([sessionId, branch]) => [
                    sessionId,
                    {
                        base: revisionTagCodec.encode(branch.base, {
                            originatorId: sessionId,
                            idCompressor: context.idCompressor,
                            revision: undefined,
                        }),
                        commits: branch.commits.map((commit) => encodeCommit(commit, {
                            originatorId: commit.sessionId,
                            idCompressor: context.idCompressor,
                            schema: context.schema,
                            revision: undefined,
                        })),
                    },
                ]),
                version,
            };
            return json;
        },
        decode: (json, context) => {
            // TODO: sort out EncodedCommit vs Commit, and make this type check without `any`.
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            const trunk = json.trunk;
            return {
                trunk: trunk.map((commit) => 
                // TODO: sort out EncodedCommit vs Commit, and make this type check without `as`.
                // eslint-disable-next-line @typescript-eslint/no-unsafe-return
                decodeCommit(commit, {
                    originatorId: commit.sessionId,
                    idCompressor: context.idCompressor,
                    revision: undefined,
                })),
                peerLocalBranches: new Map(mapIterable(json.branches, ([sessionId, branch]) => [
                    sessionId,
                    {
                        base: revisionTagCodec.decode(branch.base, {
                            originatorId: sessionId,
                            idCompressor: context.idCompressor,
                            revision: undefined,
                        }),
                        commits: branch.commits.map((commit) => 
                        // TODO: sort out EncodedCommit vs Commit, and make this type check without `as`.
                        decodeCommit(commit, {
                            originatorId: commit.sessionId,
                            idCompressor: context.idCompressor,
                            revision: undefined,
                        })),
                    },
                ])),
            };
        },
    }, options.jsonValidator);
    // TODO: makeVersionedValidatedCodec and withSchemaValidation should allow the codec to decode JsonCompatibleReadOnly, or Versioned or something like that,
    // and not leak the internal encoded format in the API surface.
    // Fixing that would remove the need for this cast.
    return codec;
}
//# sourceMappingURL=editManagerCodecs.js.map