/*!
 * 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, TContext, TFormatVersion extends FormatVersion = FormatVersion>(discontinuedVersion: TFormatVersion, discontinuedSince: SemanticVersion): CodecVersion<TDecoded, TContext, TFormatVersion>;
/**
 * 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, TContext = void> = {
    readonly schema: TSchema;
} & IJsonCodec<TDecoded, VersionedJson, JsonCompatibleReadOnly, TContext>;
/**
 * 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, TContext, TFormatVersion extends FormatVersion, TBuildOptions extends ICodecOptions = ICodecOptions> extends CodecVersionBase<CodecAndSchema<TDecoded, TContext> | ((options: TBuildOptions) => CodecAndSchema<TDecoded, TContext>), TFormatVersion> {
}
/**
 * {@link CodecVersion} after normalization into a consistent type.
 * @remarks
 * Produced by {@link normalizeCodecVersion}.
 * Includes schema validation.
 */
export interface NormalizedCodecVersion<TDecoded, TContext, TFormatVersion extends FormatVersion, TBuildOptions extends ICodecOptions> extends CodecVersionBase<(options: TBuildOptions) => CodecAndSchema<TDecoded, TContext>, TFormatVersion> {
}
/**
 * {@link NormalizedCodecVersion} after applying the build options.
 * @remarks
 * Produced by {@link ClientVersionDispatchingCodecBuilder.applyOptions}.
 */
interface EvaluatedCodecVersion<TDecoded, TContext, TFormatVersion extends FormatVersion> extends CodecVersionBase<CodecAndSchema<TDecoded, TContext>, TFormatVersion> {
}
/**
 * Creates a codec which dispatches to the appropriate member of a codec family based on the `minVersionForCollab` for encode and the
 * version number in data it encounters for decode.
 * @privateRemarks
 * This is a two stage builder so the first stage can encapsulate all codec specific details and the second can bring in configuration.
 */
export declare class ClientVersionDispatchingCodecBuilder<TBuildOptions extends ICodecOptions = ICodecOptions, TDecoded = unknown, TContext = unknown, TFormatVersion extends FormatVersion = FormatVersion, TName extends CodecName = string> {
    /**
     * See {@link CodecName}.
     */
    readonly name: TName;
    readonly registry: readonly NormalizedCodecVersion<TDecoded, TContext, TFormatVersion, TBuildOptions>[];
    /**
     * Use {@link ClientVersionDispatchingCodecBuilder.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 the provided 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, TContext, TFormatVersion>[];
    /**
     * Produce a single codec which can read any supported format, and writes a version selected based on the provided options.
     */
    build(options: TBuildOptions & CodecWriteOptions): IJsonCodec<TDecoded, JsonCompatibleReadOnly, JsonCompatibleReadOnly, TContext> & {
        /**
         * The format version which this codec writes.
         * @remarks
         * This is selected based on the provided {@link CodecWriteOptions}.
         */
        readonly writeVersion: TFormatVersion;
    };
    private buildDecoderInternal;
    /**
     * Produce a single codec which can read any supported format.
     */
    buildDecoder(options: TBuildOptions): Pick<IJsonCodec<TDecoded, JsonCompatibleReadOnly, JsonCompatibleReadOnly, TContext>, "decode">;
    getCodecTree(clientVersion: MinimumVersionForCollab): CodecTree<TFormatVersion>;
    /**
     * Builds a ClientVersionDispatchingCodecBuilder from the provided 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.
     */
    static build<Name extends CodecName, Entry extends CodecVersion<unknown, unknown, FormatVersion, never>>(name: Name, inputRegistry: readonly Entry[]): ClientVersionDispatchingCodecBuilder<Entry extends CodecVersion<unknown, unknown, FormatVersion, infer B extends ICodecOptions> ? B : never, Entry extends CodecVersion<infer D, unknown, FormatVersion, never> ? D : never, unknown extends (Entry extends CodecVersion<unknown, infer C, FormatVersion, never> ? C : never) ? void : Entry extends CodecVersion<unknown, infer C, FormatVersion, never> ? C : never, Entry extends CodecVersion<unknown, unknown, infer F extends FormatVersion, never> ? F : never, Name>;
}
export {};
//# sourceMappingURL=codec.d.ts.map