import type { Animation, Audio, Contact, Context, Dice, Document, File, Game, Location, MessageEntity, PaidMediaInfo, PhotoSize, Poll, Sticker, Story, Venue, Video, VideoNote, Voice } from "./deps.node.js";
/**
 * An action to perform after a context object passed form valiation.
 *
 * A form action receives the validated context object as the first argument. It
 * receives the extracted value as a second argument.
 *
 * @param ctx The current context object
 * @param result The value returned by the form field
 * @typeParam C A custom context type
 * @typeParam T The type of form field
 */
export type FormAction<C extends Context, T> = (ctx: C, result: T) => unknown | Promise<unknown>;
/**
 * A callback function to be invoked after a context object failed form
 * validation.
 *
 * A form action receives the rejected context object as the first argument.
 *
 * If validation fails and an error is specified, it is possible to use
 * {@link OtherwiseWithReason} instead.
 *
 * @param ctx The current context object
 * @typeParam C A custom context type
 */
export type Otherwise<C extends Context> = (ctx: C) => unknown | Promise<unknown>;
/**
 * A callback function to be invoked after a context object failed form
 * validation.
 *
 * A form action receives the rejected context object as the first argument.
 *
 * If validation fails and a reason is specified as an error of the
 * {@link Result} return value of the validation function, the form action
 * receives the error as a second argument. If no reason was specified, use
 * {@link Otherwise} instead.
 *
 * @param ctx The current context object
 * @param reason A reason why validation failed
 * @typeParam C A custom context type
 * @typeParam R A type of reason defined by the validation function
 */
export type OtherwiseWithReason<C extends Context, R> = (ctx: C, reason: R) => unknown | Promise<unknown>;
/**
 * Options to pass to a form field. Can be either a {@link FormAction} function
 * or a {@link FormConfig} object.
 *
 * If the validation function is able to provide a reason as to why validation
 * has failed, it is possible use {@link FormOptionsWithReason} instead.
 *
 * @typeParam C A custom context type
 * @typeParam C A form field type
 */
export type FormOptions<C extends Context, T> = FormAction<C, T> | FormConfig<C, T>;
/**
 * Options to pass to a form field with an enhanced validation function that can
 * provide a reason as to why validation has failed. Can be either a
 * {@link FormAction} function or a {@link FormConfigWithReason} object.
 *
 * If the validation function does not provide a reason, use {@link FormOptions}
 * instead.
 *
 * @typeParam C A custom context type
 * @typeParam T A type of success value for the validation function
 * @typeParam R A type of error value for the validation function
 */
export type FormOptionsWithReason<C extends Context, T, R> = FormAction<C, T> | FormConfigWithReason<C, T, R>;
/**
 * A base options bag object for a form field. This holds all properties that
 * are common among {@link FormConfig} and {@link FormConfigWithReason}.
 *
 * @typeParam C A custom context type
 * @typeParam T A form field type
 */
export interface FormConfigShared<C extends Context, T> {
    /**
     * Determines whether [the outside middleware
     * system](https://grammy.dev/guide/middleware) should resume after the
     * update is skipped in case that form validation fails.
     *
     * Specify `next: true` to make sure that subsequent handlers will run. This
     * effectively causes `next` to be called by the plugin.
     *
     * Defaults to `false` unless the conversation is marked as parallel, in
     * which case this option defaults to `true`.
     */
    next?: boolean;
    /**
     * Specifies a timeout for the wait call.
     *
     * When the form field is reached, `Date.now()` is called. When the form
     * field resolves, `Date.now()` is called again, and the two values are
     * compared. If the form field resolved more than the specified number of
     * milliseconds after it was reached initially, then the conversation will
     * be halted, any exit handlers will be called, and the surrounding
     * middleware will resume normally so that subsequent handlers can run.
     *
     * To the outside middleware system, this will look like the conversation
     * was never active.
     */
    maxMilliseconds?: number;
    /**
     * Collation key for the wait call, safety measure to protect against data
     * corruption. This is used extensively by the plugin internally, but it is
     * rarely useful to changes this behavior.
     */
    collationKey?: string;
    /**
     * A form action to perform on the context object after the form validation
     * succeeds for a context object, and before the respective value is
     * returned form the form field.
     */
    action?: FormAction<C, T>;
}
/**
 * An options bag object for a form field. Contains all properties of
 * {@link FormConfigShared} as well as an `otherwise` function to be invoked
 * when form valiation fails.
 *
 * If a reason is specified by the form validation, it is possible to use
 * {@link FormConfigWithReason} instead.
 *
 * @typeParam C A custom context type
 * @typeParam T A form field type
 */
export interface FormConfig<C extends Context, T> extends FormConfigShared<C, T> {
    /**
     * Callback that will be invoked when the form validation fails for a
     * context object.
     */
    otherwise?: Otherwise<C>;
}
/**
 * An options bag object for a form field. Contains all properties of
 * {@link FormConfigShared} as well as an `otherwise` function to be invoked
 * when form valiation fails with a known reason.
 *
 * If no reason is specified by the form validation, use {@link FormConfig}
 * instead.
 *
 * @typeParam C A custom context type
 * @typeParam T A type of success value for the validation function
 * @typeParam R A type of error value for the validation function
 */
export interface FormConfigWithReason<C extends Context, T, R> extends FormConfigShared<C, T> {
    /**
     * Callback that will be invoked when the form validation fails with a
     * reason for a context object.
     */
    otherwise?: OtherwiseWithReason<C, R>;
}
/** A value that may be absent */
export type Maybe<T> = {
    ok: false;
} | {
    ok: true;
    value: T;
};
/** A value or an error */
export type Result<T, E> = {
    ok: false;
    error: E;
} | {
    ok: true;
    value: T;
};
/**
 * An object that fully specifies how to build a form field.
 *
 * Contains as properties of {@link FormConfig} as well as a function that can
 * validate context objects.
 *
 * If the validation function can provide a reason as to why validation has
 * failed, it is possible to use {@link FormBuilderWithReason} instead.
 *
 * @typeParam C A custom context type
 * @typeParam T The type of value this form field returns
 */
export interface FormBuilder<C extends Context, T> extends FormConfig<C, T> {
    /**
     * A function that validates a given context.
     *
     * When validation succeeds, a value can be extracted from the context
     * object. The result of the validation as well as the data extraction needs
     * to be encoded using a {@link Maybe} type.
     *
     * @param ctx A context object to validate
     */
    validate(ctx: C): Maybe<T> | Promise<Maybe<T>>;
}
/**
 * An object that fully specifies how to build a form field.
 *
 * Contains as properties of {@link FormConfigWithReason} as well as a function
 * that can validate context objects. If a context object does not pass
 * validation, the validation function is able to provide a reason.
 *
 * If the validation function cannot provide reason as to why validation has
 * failed, it is possible to use {@link FormBuilder} instead.
 *
 * @typeParam C A custom context type
 * @typeParam T A type of success value for the validation function
 * @typeParam R A type of error value for the validation function
 */
export interface FormBuilderWithReason<C extends Context, T, R> extends FormConfigWithReason<C, T, R> {
    /**
     * A function that validates a given context.
     *
     * When validation succeeds, a value can be extracted from the context
     * object. When validation fails, an error can be generated. The result of
     * the validation needs to be encoded using a {@link Result} type.
     *
     * @param ctx A context object to validate
     */
    validate(ctx: C): Result<T, R> | Promise<Result<T, R>>;
}
/**
 * A container for form building utilities.
 *
 * Each method on this class represents a differnt type of form field which can
 * validate context objects and extract data from it.
 */
export declare class ConversationForm<C extends Context> {
    private readonly conversation;
    /** Constructs a new form based on wait and skip callbacks */
    constructor(conversation: {
        wait: (opts: {
            maxMilliseconds?: number;
            collationKey?: string;
        }) => Promise<C>;
        skip: (opts: {
            next?: boolean;
        }) => Promise<never>;
    });
    /**
     * Generic form field that can be used to build any other type of form
     * field. This is heavily used internally.
     *
     *  Most likely, you will not need this because there is a more convenient
     *  option. However, you can still use it if the type of form field you need
     *  is not supported out of the box.
     *
     * @param builder A form field definition object
     * @typeParam T A type of value to be extracted from the form field
     * @typeParam R A type of reason to be specified if validation fails
     */
    build<T, R>(builder: FormBuilderWithReason<C, T, R>): Promise<T>;
    build<T, R>(builder: FormBuilder<C, T>): Promise<T>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with text, and returns this text as string. Does not check
     * for captions.
     *
     * Accepts an optional options object that lets you perform actions when
     * text is received, when a non-text update is received, and more.
     *
     * @param options Optional options
     */
    text(options?: FormOptions<C, string>): Promise<string>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with text that can be parsed to a number, and returns this
     * number. Does not check captions.
     *
     * The conversion to number uses `parseFloat`.
     *
     * Accepts an optional options object that lets you perform actions when a
     * number is received, when a non-number update is received, and more.
     *
     * @param options Optional options
     */
    number(options?: FormOptions<C, number>): Promise<number>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with text that can be parsed to an integer, and returns this
     * integer as a `number`. Does not check for captions.
     *
     * The conversion to number uses `parseInt`.
     *
     * Accepts an optional options object that lets you specify the radix to use
     * as well as perform actions when a number is received, when a non-number
     * update is received, and more.
     *
     * @param options Optional options
     */
    int(options?: FormOptions<C, number> & {
        /** The radix to use for parsing the integer */
        radix?: number;
    }): Promise<number>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with one of several predefined strings, and returns the
     * actual text as string. Does not check captions.
     *
     * This is especially useful when working with custom keyboards.
     *
     * ```ts
     * const keyboard = new Keyboard()
     *   .text("A").text("B")
     *   .text("C").text("D")
     *   .oneTime()
     * await ctx.reply("A, B, C, or D?", { reply_markup: keyboard })
     * const answer = await conversation.form.select(["A", "B", "C", "D"], {
     *   otherwise: ctx => ctx.reply("Please use one of the buttons!")
     * })
     * switch (answer) {
     *   case "A":
     *   case "B":
     *   case "C":
     *   case "D":
     *   // ...
     * }
     * ```
     *
     * Accepts an optional options object that lets you perform actions when
     * text is received, when a non-text update is received, and more.
     *
     * @param entries A string array of accepted values
     * @param options Optional options
     */
    select<E extends string>(entries: E[], options?: FormOptions<C, E>): Promise<E>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a given type of message entity, and returns this
     * entity. The form field relies on `ctx.entities()` for data extraction, so
     * both texts and captions are checked.
     *
     * Accepts an optional options object that lets you perform actions when
     * text is received, when a non-text update is received, and more.
     *
     * @param type One or more types of message entities to accept
     * @param options Optional options
     */
    entity<M extends MessageEntity>(type: M["type"] | M["type"][], options?: FormOptions<C, MessageEntity & {
        text: string;
    }>): Promise<MessageEntity & {
        text: string;
    }>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with an animation, and returns the received animation
     * object.
     *
     * Accepts an optional options object that lets you perform actions when an
     * animation is received, when a non-animation update is received, and more.
     *
     * @param options Optional options
     */
    animation(options?: FormOptions<C, Animation>): Promise<Animation>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with an audio message, and returns the received audio
     * object.
     *
     * Accepts an optional options object that lets you perform actions when an
     * audio message is received, when a non-audio update is received, and more.
     *
     * @param options Optional options
     */
    audio(options?: FormOptions<C, Audio>): Promise<Audio>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a document message, and returns the received document
     * object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * document message is received, when a non-document update is received, and
     * more.
     *
     * @param options Optional options
     */
    document(options?: FormOptions<C, Document>): Promise<Document>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with paid media, and returns the received paid media object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * paid media message is received, when a non-paid media update is received,
     * and more.
     *
     * @param options Optional options
     */
    paidMedia(options?: FormOptions<C, PaidMediaInfo>): Promise<PaidMediaInfo>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a photo, and returns the received array of `PhotoSize`
     * objects.
     *
     * Accepts an optional options object that lets you perform actions when a
     * photo is received, when a non-photo update is received, and more.
     *
     * @param options Optional options
     */
    photo(options?: FormOptions<C, PhotoSize[]>): Promise<PhotoSize[]>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a sticker, and returns the received sticker object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * sticker is received, when a non-sticker update is received, and more.
     *
     * @param options Optional options
     */
    sticker(options?: FormOptions<C, Sticker>): Promise<Sticker>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a story, and returns the received story object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * story is received, when a non-story update is received, and more.
     *
     * @param options Optional options
     */
    story(options?: FormOptions<C, Story>): Promise<Story>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a video, and returns the received video object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * video is received, when a non-video update is received, and more.
     *
     * @param options Optional options
     */
    video(options?: FormOptions<C, Video>): Promise<Video>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a video note, and returns the received video note
     * object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * video note is received, when a non-video note update is received, and
     * more.
     *
     * @param options Optional options
     */
    video_note(options?: FormOptions<C, VideoNote>): Promise<VideoNote>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a voice message, and returns the received voice object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * voice message is received, when a non-voice message update is received,
     * and more.
     *
     * @param options Optional options
     */
    voice(options?: FormOptions<C, Voice>): Promise<Voice>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a contact, and returns the received contact object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * contact is received, when a non-contact update is received, and more.
     *
     * @param options Optional options
     */
    contact(options?: FormOptions<C, Contact>): Promise<Contact>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with dice, and returns the received dice object.
     *
     * Accepts an optional options object that lets you perform actions when
     * dice are received, when a non-dice update is received, and more.
     *
     * @param options Optional options
     */
    dice(options?: FormOptions<C, Dice>): Promise<Dice>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a game, and returns the received game object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * game is received, when a non-game update is received, and more.
     *
     * @param options Optional options
     */
    game(options?: FormOptions<C, Game>): Promise<Game>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a poll, and returns the received poll object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * poll is received, when a non-poll update is received, and more.
     *
     * @param options Optional options
     */
    poll(options?: FormOptions<C, Poll>): Promise<Poll>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a venue, and returns the received venue object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * venue is received, when a non-venue update is received, and more.
     *
     * @param options Optional options
     */
    venue(options?: FormOptions<C, Venue>): Promise<Venue>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a location, and returns the received location object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * location is received, when a non-location update is received, and more.
     *
     * @param options Optional options
     */
    location(options?: FormOptions<C, Location>): Promise<Location>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a photo or video, and returns the received media
     * object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * media is received, when a non-media update is received, and more.
     *
     * @param options Optional options
     */
    media(options?: FormOptions<C, PhotoSize[] | Video>): Promise<PhotoSize[] | Video>;
    /**
     * Form field that checks if the incoming update contains a message or
     * channel post with a file, calls `await ctx.getFile()`, and returns the
     * received file object.
     *
     * Accepts an optional options object that lets you perform actions when a
     * file is received, when a non-file update is received, and more.
     *
     * @param options Optional options
     */
    file(options?: FormOptions<C, File>): Promise<File>;
}
