/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
import { type SemanticVersion } from "@fluidframework/runtime-utils/internal";
import type { TSchema } from "@sinclair/typebox";
import { type JsonCompatibleReadOnly, type JsonCompatibleReadOnlyObject } from "../../util/index.js";
import { type ICodecOptions, type IJsonCodec, type FormatVersion, type CodecWriteOptions, type CodecName, type CodecTree } from "../codec.js";
import { Versioned } from "./format.js";
/**
 * Json compatible data with a format version.
 */
type VersionedJson = JsonCompatibleReadOnlyObject & Versioned;
/**
 * Creates a codec version which always throws a UsageError when encoding or decoding, indicating that the format version is discontinued.
 */
export declare function makeDiscontinuedCodecAndSchema<TDecoded, TFormatVersion extends FormatVersion = FormatVersion>(discontinuedVersion: TFormatVersion, discontinuedSince: SemanticVersion): CodecVersion<TDecoded, unknown, TFormatVersion, ICodecOptions, unknown>;
/**
 * A friendly format for codec authors use to define their codec and schema for use in {@link CodecVersion}.
 * @remarks
 * The codec should not perform its own schema validation.
 * The schema validation gets added when normalizing to {@link NormalizedCodecVersion}.
 */
export type CodecAndSchema<TDecoded, TEncodeContext = void, TDecodeContext = TEncodeContext> = {
    readonly schema: TSchema;
} & IJsonCodec<TDecoded, VersionedJson, JsonCompatibleReadOnly, TEncodeContext, TDecodeContext>;
/**
 * A codec alongside its format version and schema.
 */
export interface CodecVersionBase<T = unknown, TFormatVersion extends FormatVersion = FormatVersion> {
    /**
     * When `undefined` the codec will never be selected as a write version except via override.
     * @remarks
     * This format will be used for decode if data in it needs to be decoded, regardless of `minVersionForCollab`.
     * `undefined` should be used for unstable codec versions (with string FormatVersions),
     * as well as previously stabilized formats that are discontinued (meaning we always prefer to use some other format for encoding).
     */
    readonly minVersionForCollab: MinimumVersionForCollab | undefined;
    readonly formatVersion: TFormatVersion;
    readonly codec: T;
}
/**
 * A particular version of a codec and when to use it.
 * @privateRemarks
 * This allows lazy building of the codec with options.
 * This option can likely be removed as the codec handling is made simpler and more consistent.
 * Removing support for this laziness would be nice to help prevent unexpected coupling and alteration to codec behavior,
 * helping ensure that tests and production code behave the same.
 */
export interface CodecVersion<TDecoded, TEncodeContext, TFormatVersion extends FormatVersion, TBuildOptions extends ICodecOptions = ICodecOptions, TDecodeContext = TEncodeContext> extends CodecVersionBase<CodecAndSchema<TDecoded, TEncodeContext, TDecodeContext> | ((options: TBuildOptions) => CodecAndSchema<TDecoded, TEncodeContext, TDecodeContext>), TFormatVersion> {
}
/**
 * {@link CodecVersion} after normalization into a consistent type.
 * @remarks
 * Produced by {@link normalizeCodecVersion}.
 * Includes schema validation.
 */
export interface NormalizedCodecVersion<TDecoded, TEncodeContext, TFormatVersion extends FormatVersion, TBuildOptions extends ICodecOptions, TDecodeContext = TEncodeContext> extends CodecVersionBase<(options: TBuildOptions) => CodecAndSchema<TDecoded, TEncodeContext, TDecodeContext>, TFormatVersion> {
}
/**
 * {@link NormalizedCodecVersion} after applying the build options.
 * @remarks
 * Produced by {@link VersionDispatchingCodecBuilder.applyOptions}.
 */
interface EvaluatedCodecVersion<TDecoded, TEncodeContext, TFormatVersion extends FormatVersion, TDecodeContext = TEncodeContext> extends CodecVersionBase<CodecAndSchema<TDecoded, TEncodeContext, TDecodeContext>, TFormatVersion> {
}
/**
 * A codec that can read multiple format versions and write a single selected version.
 * @remarks
 * Produced by {@link VersionDispatchingCodecBuilder.build}.
 *
 * @typeParam TDecoded - The in memory (not encoded) format.
 * @typeParam TEncodeContext - Context type passed to encode operations.
 * @typeParam TFormatVersion - The type of format version identifiers used by this codec.
 * @typeParam TDecodeContext - Context type passed to decode operations. Defaults to `TEncodeContext`.
 */
export interface VersionDispatchingCodec<TDecoded, TEncodeContext, TFormatVersion extends FormatVersion, TDecodeContext = TEncodeContext> extends IJsonCodec<TDecoded, JsonCompatibleReadOnly, JsonCompatibleReadOnly, TEncodeContext, TDecodeContext> {
    /**
     * The format version which this codec writes.
     * @remarks
     * Selected by {@link VersionDispatchingCodecBuilder.build} based on the provided options.
     */
    readonly writeVersion: TFormatVersion;
}
/**
 * Creates a {@link VersionDispatchingCodec} using a {@link CodecVersion} to select the {@link VersionDispatchingCodec.writeVersion}.
 * @privateRemarks
 * This is a two stage builder so the first stage (the static build) can encapsulate all codec specific details and
 * the second (the instance build) can bring in configuration.
 */
export declare class VersionDispatchingCodecBuilder<TBuildOptions extends ICodecOptions = ICodecOptions, TDecoded = unknown, TEncodeContext = unknown, TFormatVersion extends FormatVersion = FormatVersion, TName extends CodecName = string, TDecodeContext = TEncodeContext> {
    /**
     * See {@link CodecName}.
     */
    readonly name: TName;
    readonly registry: readonly NormalizedCodecVersion<TDecoded, TEncodeContext, TFormatVersion, TBuildOptions, TDecodeContext>[];
    /**
     * Use {@link VersionDispatchingCodecBuilder.build} to create an instance of this class.
     * @remarks
     * Inputs to this are assumed to be constants in the code controlled by the developers of this package,
     * and constructed at least once during tests.
     * Because of this, the validation of these inputs done with debugAssert should be sufficient,
     * and using debugAssert avoids bloating the bundle size for production users.
     */
    private constructor();
    /**
     * Applies `options` to the codec registry to produce a list of evaluated codecs.
     * @remarks
     * This is used by build, which is what production code should use.
     * This is only exposed for testing purposes.
     */
    applyOptions(options: TBuildOptions): EvaluatedCodecVersion<TDecoded, TEncodeContext, TFormatVersion, TDecodeContext>[];
    /**
     * Builds a complete {@link VersionDispatchingCodec} that can decode all registered versions
     * and encode a version selected by the provided options.
     */
    build(options: TBuildOptions & CodecWriteOptions): VersionDispatchingCodec<TDecoded, TEncodeContext, TFormatVersion, TDecodeContext>;
    private buildDecoderInternal;
    /**
     * Builds a decoder-only codec that can decode any supported format without encoding capability.
     *
     * @remarks
     * The returned codec contains only the `decode` method and can be used when only decoding is needed.
     * This is useful for scenarios where reading/decoding versioned data is sufficient.
     *
     * @param options - Build options (typically containing the `jsonValidator`)
     * @returns An object with a `decode` method that can handle any supported format version
     */
    buildDecoder(options: TBuildOptions): Pick<VersionDispatchingCodec<TDecoded, TEncodeContext, TFormatVersion, TDecodeContext>, "decode">;
    getCodecTree(clientVersion: MinimumVersionForCollab): CodecTree<TFormatVersion>;
    /**
     * Creates a new VersionDispatchingCodecBuilder from the provided codec registry.
     *
     * @remarks
     * This static method infers the types of the builder from the provided registry,
     * making it easier to create builders without needing to explicitly specify all type parameters.
     * This gets better type inference than the constructor.
     *
     * @example
     * ```typescript
     * const builder = VersionDispatchingCodecBuilder.build('myCodec', [
     *   { minVersionForCollab: lowestMinVersionForCollab, formatVersion: 1, codec: { encode, decode, schema } },
     *   { minVersionForCollab: '2.100.0', formatVersion: 2, codec: { encode, decode, schema } },
     * ]);
     * ```
     */
    static build<Name extends CodecName, Entry extends CodecVersion<unknown, unknown, FormatVersion, never, unknown>>(name: Name, inputRegistry: readonly Entry[]): VersionDispatchingCodecBuilder<Entry extends CodecVersion<unknown, unknown, FormatVersion, infer B extends ICodecOptions, unknown> ? B : never, Entry extends CodecVersion<infer D, unknown, FormatVersion, never, unknown> ? D : never, unknown extends (Entry extends CodecVersion<unknown, infer C, FormatVersion, never, unknown> ? C : never) ? void : Entry extends CodecVersion<unknown, infer C, FormatVersion, never, unknown> ? C : never, Entry extends CodecVersion<unknown, unknown, infer F extends FormatVersion, never, unknown> ? F : never, Name, unknown extends (Entry extends CodecVersion<unknown, unknown, FormatVersion, never, infer D_1> ? D_1 : never) ? unknown extends (Entry extends CodecVersion<unknown, infer C, FormatVersion, never, unknown> ? C : never) ? void : Entry extends CodecVersion<unknown, infer C, FormatVersion, never, unknown> ? C : never : Entry extends CodecVersion<unknown, unknown, FormatVersion, never, infer D_1> ? D_1 : never>;
}
export {};
//# sourceMappingURL=codec.d.ts.map