import type { EndpointV2 } from "../endpoint";
import type { HandlerExecutionContext } from "../middleware";
import type { MetadataBearer } from "../response";
import type { EndpointBearer, SerdeFunctions } from "../serde";
import type { BigDecimalSchema, BigIntegerSchema, BlobSchema, BooleanSchema, DocumentSchema, NumericSchema, StreamingBlobSchema, StringSchema, TimestampDateTimeSchema, TimestampDefaultSchema, TimestampEpochSecondsSchema, TimestampHttpDateSchema } from "./sentinels";
import type { TraitBitVector } from "./traits";
/**
 * A schema is an object or value that describes how to serialize/deserialize data.
 * @public
 */
export type Schema = UnitSchema | TraitsSchema | SimpleSchema | ListSchema | MapSchema | StructureSchema | MemberSchema | OperationSchema | NormalizedSchema;
/**
 * Traits attached to schema objects.
 *
 * When this is a number, it refers to a pre-allocated
 * trait combination that is equivalent to one of the
 * object type's variations.
 *
 * @public
 */
export type SchemaTraits = TraitBitVector | SchemaTraitsObject;
/**
 * A schema that has traits.
 *
 * @public
 */
export interface TraitsSchema {
    name: string;
    traits: SchemaTraits;
}
/**
 * Simple schemas are those corresponding to simple Smithy types.
 * @see https://smithy.io/2.0/spec/simple-types.html
 * @public
 */
export type SimpleSchema = BlobSchemas | StringSchema | BooleanSchema | NumericSchema | BigIntegerSchema | BigDecimalSchema | DocumentSchema | TimestampSchemas | number;
/**
 * Sentinel value for Timestamp schema.
 * "Default" means unspecified and to use the protocol serializer's default format.
 *
 * @public
 */
export type TimestampSchemas = TimestampDefaultSchema | TimestampDateTimeSchema | TimestampHttpDateSchema | TimestampEpochSecondsSchema;
/**
 * Sentinel values for Blob schema.
 * @public
 */
export type BlobSchemas = BlobSchema | StreamingBlobSchema;
/**
 * Signal value for the Smithy void value. Typically used for
 * operation input and outputs.
 *
 * @internal
 */
export type UnitSchema = "unit";
/**
 * See https://smithy.io/2.0/trait-index.html for individual definitions.
 *
 * @public
 */
export type SchemaTraitsObject = {
    idempotent?: 1;
    idempotencyToken?: 1;
    sensitive?: 1;
    sparse?: 1;
    /**
     * timestampFormat is expressed by the schema sentinel values of 4, 5, 6, and 7,
     * and not contained in trait objects.
     * @deprecated use schema value.
     */
    timestampFormat?: never;
    httpLabel?: 1;
    httpHeader?: string;
    httpQuery?: string;
    httpPrefixHeaders?: string;
    httpQueryParams?: 1;
    httpPayload?: 1;
    /**
     * [method, path, statusCode]
     */
    http?: [string, string, number];
    httpResponseCode?: 1;
    /**
     * [hostPrefix]
     */
    endpoint?: [string];
    xmlAttribute?: 1;
    xmlName?: string;
    /**
     * [prefix, uri]
     */
    xmlNamespace?: [string, string];
    xmlFlattened?: 1;
    jsonName?: string;
    mediaType?: string;
    error?: "client" | "server";
    [traitName: string]: unknown;
};
/**
 * Schema for the structure aggregate type.
 * @public
 */
export interface StructureSchema extends TraitsSchema {
    name: string;
    traits: SchemaTraits;
    members: Record<string, [SchemaRef, SchemaTraits]>;
}
/**
 * Schema for the list aggregate type.
 * @public
 */
export interface ListSchema extends TraitsSchema {
    name: string;
    traits: SchemaTraits;
    valueSchema: SchemaRef;
}
/**
 * Schema for the map aggregate type.
 * @public
 */
export interface MapSchema extends TraitsSchema {
    name: string;
    traits: SchemaTraits;
    keySchema: SchemaRef;
    valueSchema: SchemaRef;
}
/**
 * @public
 */
export type MemberSchema = [SchemaRef, SchemaTraits];
/**
 * Schema for an operation.
 *
 * @public
 */
export interface OperationSchema extends TraitsSchema {
    name: string;
    traits: SchemaTraits;
    input: SchemaRef;
    output: SchemaRef;
}
/**
 * Normalization wrapper for various schema data objects.
 * @internal
 */
export interface NormalizedSchema extends TraitsSchema {
    name: string;
    traits: SchemaTraits;
    getSchema(): Schema;
    getName(): string | undefined;
    isMemberSchema(): boolean;
    isListSchema(): boolean;
    isMapSchema(): boolean;
    isStructSchema(): boolean;
    isBlobSchema(): boolean;
    isTimestampSchema(): boolean;
    isStringSchema(): boolean;
    isBooleanSchema(): boolean;
    isNumericSchema(): boolean;
    isBigIntegerSchema(): boolean;
    isBigDecimalSchema(): boolean;
    isStreaming(): boolean;
    getMergedTraits(): SchemaTraitsObject;
    getMemberTraits(): SchemaTraitsObject;
    getOwnTraits(): SchemaTraitsObject;
    /**
     * For list/set/map.
     */
    getValueSchema(): NormalizedSchema;
    /**
     * For struct/union.
     */
    getMemberSchema(member: string): NormalizedSchema | undefined;
    getMemberSchemas(): Record<string, NormalizedSchema>;
}
/**
 * A schema "reference" is either a schema or a function that
 * provides a schema. This is useful for lazy loading, and to allow
 * code generation to define schema out of dependency order.
 * @public
 */
export type SchemaRef = Schema | (() => Schema);
/**
 * A codec creates serializers and deserializers for some format such as JSON, XML, or CBOR.
 *
 * @public
 */
export interface Codec<S, D> extends ConfigurableSerdeContext {
    createSerializer(): ShapeSerializer<S>;
    createDeserializer(): ShapeDeserializer<D>;
}
/**
 * Configuration for codecs. Different protocols may share codecs, but require different behaviors from them.
 *
 * @public
 */
export type CodecSettings = {
    timestampFormat: {
        /**
         * Whether to use member timestamp format traits.
         */
        useTrait: boolean;
        /**
         * Default timestamp format.
         */
        default: TimestampDateTimeSchema | TimestampHttpDateSchema | TimestampEpochSecondsSchema;
    };
    /**
     * Whether to use HTTP binding traits.
     */
    httpBindings?: boolean;
};
/**
 * Turns a serialization into a data object.
 * @public
 */
export interface ShapeDeserializer<SerializationType = Uint8Array> extends ConfigurableSerdeContext {
    /**
     * Optionally async.
     */
    read(schema: Schema, data: SerializationType): any | Promise<any>;
}
/**
 * Turns a data object into a serialization.
 * @public
 */
export interface ShapeSerializer<SerializationType = Uint8Array> extends ConfigurableSerdeContext {
    write(schema: Schema, value: unknown): void;
    flush(): SerializationType;
}
/**
 * A client protocol defines how to convert a message (e.g. HTTP request/response) to and from a data object.
 * @public
 */
export interface ClientProtocol<Request, Response> extends ConfigurableSerdeContext {
    /**
     * @returns the Smithy qualified shape id.
     */
    getShapeId(): string;
    getRequestType(): {
        new (...args: any[]): Request;
    };
    getResponseType(): {
        new (...args: any[]): Response;
    };
    /**
     * @returns the payload codec if the requests/responses have a symmetric format.
     * It otherwise may return null.
     */
    getPayloadCodec(): Codec<any, any>;
    serializeRequest<Input extends object>(operationSchema: OperationSchema, input: Input, context: HandlerExecutionContext & SerdeFunctions & EndpointBearer): Promise<Request>;
    updateServiceEndpoint(request: Request, endpoint: EndpointV2): Request;
    deserializeResponse<Output extends MetadataBearer>(operationSchema: OperationSchema, context: HandlerExecutionContext & SerdeFunctions, response: Response): Promise<Output>;
}
/**
 * Allows a protocol, codec, or serde utility to accept the serdeContext
 * from a client configuration or request/response handlerExecutionContext.
 *
 * @public
 */
export interface ConfigurableSerdeContext {
    setSerdeContext(serdeContext: SerdeFunctions): void;
}
