import { JSONSchema4Object, JSONSchema6Object, JSONSchema7Object } from 'json-schema';
import { OpenAPIV2, OpenAPIV3_1, OpenAPIV3 } from 'openapi-types';

type APIDocument<T extends object = NonNullable<unknown>> = OpenAPIV2.Document<T> | OpenAPIV3_1.Document<T> | OpenAPIV3.Document<T>;
type JSONSchemaObject = JSONSchema4Object | JSONSchema6Object | JSONSchema7Object;
interface ErrorDetails {
    message: string;
}
interface WarningDetails {
    message: string;
}
type ValidationResult = {
    valid: false;
    errors: ErrorDetails[];
    warnings: WarningDetails[];
    additionalErrors: number;
    specification: 'OpenAPI' | 'Swagger' | null;
} | {
    valid: true;
    warnings: WarningDetails[];
    specification: 'OpenAPI' | 'Swagger' | null;
};
interface ParserRulesOpenAPI extends Record<string, 'error' | 'warning'> {
    /**
     * Schemas that are defined as `type: array` must also have an `items` schema. The default
     * is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md#json-schema-keywords}
     */
    'array-without-items': 'error' | 'warning';
    /**
     * Parameters must be unique. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#user-content-operationparameters}
     */
    'duplicate-non-request-body-parameters': 'error' | 'warning';
    /**
     * The `operationId` definition in a path object must be unique. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#user-content-operationid}
     */
    'duplicate-operation-id': 'error' | 'warning';
    /**
     * Security schemes must only contain properties valid for their declared `type`. Catches
     * common mistakes like an `http` scheme having a `name` (which belongs to `apiKey`) before
     * AJV has a chance to surface confusing `oneOf` noise. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#security-scheme-object}
     */
    'invalid-security-scheme-properties': 'error' | 'warning';
    /**
     * Parameters that are defined within the path URI must be specified as being `required`. The
     * default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#user-content-operationparameters}
     */
    'non-optional-path-parameters': 'error' | 'warning';
    /**
     * Path parameters defined in a path URI path template must also be specified as part of that
     * paths `parameters`. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-templating}
     */
    'path-parameters-not-in-parameters': 'error' | 'warning';
    /**
     * Path parameters defined in `parameters` must also be specified in the path URI with
     * path templating. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#user-content-parametername}
     */
    'path-parameters-not-in-path': 'error' | 'warning';
}
interface ParserRulesSwagger extends Record<string, 'error' | 'warning'> {
    /**
     * Schemas that are defined as `type: array` must also have an `items` schema. The default
     * is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#schema-object}
     */
    'array-without-items': 'error' | 'warning';
    /**
     * Parameters must be unique. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-operationparameters}
     */
    'duplicate-non-request-body-parameters': 'error' | 'warning';
    /**
     * The `operationId` definition in a path object must be unique. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-operationid}
     */
    'duplicate-operation-id': 'error' | 'warning';
    /**
     * Security definitions must only contain properties valid for their declared `type`. Catches
     * common mistakes like an `apiKey` definition with `in: cookie` (which is OAS 3.0+ only)
     * before AJV has a chance to surface confusing `oneOf` noise. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#security-scheme-object}
     */
    'invalid-security-scheme-properties': 'error' | 'warning';
    /**
     * Parameters that are defined within the path URI must be specified as being `required`. The
     * default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-parameterrequired}
     */
    'non-optional-path-parameters': 'error' | 'warning';
    /**
     * Path parameters defined in a path URI path template must also be specified as part of that
     * paths `parameters`. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#parameter-object}
     */
    'path-parameters-not-in-parameters': 'error' | 'warning';
    /**
     * Path parameters defined in `parameters` must also be specified in the path URI with
     * path templating. The default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#parameter-object}
     */
    'path-parameters-not-in-path': 'error' | 'warning';
    /**
     * Schema properties that are listed as being required but don't exist within the schema. The
     * default is `error`.
     *
     * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#schema-object}
     */
    'unknown-required-schema-property': 'error' | 'warning';
}
interface ParserOptions {
    dereference?: {
        /**
         * Determines whether circular `$ref` pointers are handled.
         *
         * If set to `false`, then a `ReferenceError` will be thrown if the schema contains any
         * circular references. If set to `ignore` then circular references will be ignored and their
         * `$ref` pointers will be left alone; if you use this in conjunction with `onCircular` you
         * will be able to see which paths in the schema contain circular references.
         *
         */
        circular?: boolean | 'ignore';
        /**
         * Callback invoked during circular reference detection.
         *
         * @param path - The path that is circular (ie. the `$ref` string)
         */
        onCircular?(path: string): void;
        /**
         * Callback invoked during dereferencing.
         *
         * @param path - The path being dereferenced (ie. the `$ref` string).
         * @param value - The JSON Schema that the `$ref` resolved to.
         * @param parent - The parent of the dereferenced object.
         * @param parentPropName - The prop name of the parent object whose value was dereferenced.
         */
        onDereference?(path: string, value: JSONSchemaObject, parent?: JSONSchemaObject, parentPropName?: string): void;
    };
    resolve?: {
        /**
         * Determines whether external $ref pointers will be resolved. If this option is disabled, then
         * external `$ref` pointers will simply be ignored.
         */
        external?: boolean;
        /**
         * Determines if local files are allowed to be resolved. If this option is `true` then the
         * default behavior within `@apidevtools/json-schema-ref-parser` will be utilized.
         */
        file?: boolean;
        http?: {
            /**
             * The amount of time (in milliseconds) to wait for a response from a server when downloading
             * an API definition. The default is 5 seconds.
             */
            timeout?: number;
        };
    };
    /**
     * The maximum amount of time (in milliseconds) that JSON Schema $Ref Parser will spend dereferencing a single schema.
     * It will throw a timeout error if the operation takes longer than this.
     */
    timeoutMs?: number;
    validate?: {
        errors?: {
            /**
             * Configures if you want validation errors that are thrown to be colorized. The default is
             * `false`.
             */
            colorize?: boolean;
        };
        rules?: {
            openapi?: Partial<ParserRulesOpenAPI>;
            swagger?: Partial<ParserRulesSwagger>;
        };
    };
}

/**
 * Parses the given API definition, in JSON or YAML format, and returns it as a JSON object. This
 * method **does not** resolve `$ref` pointers or dereference anything. It simply parses _one_ file
 * and returns it.
 *
 * @param api - A file path or URL to a JSON Schema object, or the JSON Schema object itself.
 * @param options
 */
declare function parse<S extends APIDocument = APIDocument>(api: S | string, options?: ParserOptions): Promise<S>;
/**
 * Bundles all referenced files and URLs into a single API definition that only has _internal_
 * `$ref` pointers. This lets you split up your definition however you want while you're building
 * it, but later combine all those files together when it's time to package or distribute the API
 * definition to other people. The resulting definition size will be small, since it will still
 * contain _internal_ JSON references rather than being fully-dereferenced.
 *
 * @param api - A file path or URL to a JSON Schema object, or the JSON Schema object itself.
 * @param options
 */
declare function bundle<S extends APIDocument = APIDocument>(api: S | string, options?: ParserOptions): Promise<S>;
/**
 * Dereferences all `$ref` pointers in the supplied API definition, replacing each reference with
 * its resolved value. This results in an API definition that does not contain _any_ `$ref`
 * pointers. Instead, it's a normal JSON object tree that can easily be crawled and used just like
 * any other object. This is great for programmatic usage, especially when using tools that don't
 * understand JSON references.
 *
 * @param api - A file path or URL to a JSON Schema object, or the JSON Schema object itself.
 * @param options
 */
declare function dereference<S extends APIDocument = APIDocument>(api: S | string, options?: ParserOptions): Promise<S>;
/**
 * Validates the API definition against the Swagger 2.0, OpenAPI 3.0, or OpenAPI 3.1 specifications.
 *
 * In addition to validating the API definition against their respective specification schemas it
 * will also be validated against specific areas that aren't covered by the Swagger or OpenAPI
 * schemas, such as duplicate parameters, invalid component schema names, or duplicate
 * `operationId` values.
 *
 * If validation fails an error will be thrown with information about what, and where, the error
 * lies within the API definition.
 *
 * Internally this method invokes [`dereference()`](#dereference) so the returned object, whether
 * its a Swagger or OpenAPI definition, will be fully dereferenced.
 *
 * @see {@link https://github.com/OAI/OpenAPI-Specification/tree/main/schemas/v2.0}
 * @see {@link https://github.com/OAI/OpenAPI-Specification/tree/main/schemas/v3.0}
 * @see {@link https://github.com/OAI/OpenAPI-Specification/tree/main/schemas/v3.1}
 * @param api - A file path or URL to a JSON Schema object, or the JSON Schema object itself.
 * @param options
 */
declare function validate<S extends APIDocument, Options extends ParserOptions>(api: S | string, options?: Options): Promise<ValidationResult>;
/**
 * A utility to transform the `ValidationResult` from a `validate()` call into a human-readable
 * string.
 *
 */
declare function compileErrors(result: ValidationResult): string;

export { type ErrorDetails, type ParserOptions, type ValidationResult, type WarningDetails, bundle, compileErrors, dereference, parse, validate };
