import * as yup from 'yup';
import { ObjectSchema } from 'yup';
import React from 'react';

interface FormConfiguration {
    /**
     * Registered form id for this form configuration.
     */
    formId: string;
    /**
     * List of {@link ConstrainedPropertyConfiguration} instances holding property configuration for each property defined in the class that form id was mapped to.
     */
    constrainedPropertyConfigurationList: ConstrainedPropertyConfiguration[];
}
interface FormYupConfiguration<T extends Record<string, never> = any> {
    /**
     * Registered form id for this form configuration.
     */
    formId: string;
    /**
     * List of yup ObjectSchema instances holding property configuration for each property defined in the class that form id was mapped to.
     */
    yupSchema: yup.ObjectSchema<T>;
}
interface ConstrainedPropertyConfiguration {
    /**
     * Path to the property relative to a parent class that is mapped to form id.
     */
    path: string;
    /**
     * Type of constrained property.
     */
    propertyType: string;
    /**
     * JavascriptType of constrained property.
     */
    javascriptType: string;
    /**
     * List of {@link ConstrainedPropertyClientValidatorConfiguration} instances that hold client side validation configuration.
     */
    validatorList: ConstrainedPropertyClientValidatorConfiguration[];
}
interface ConstrainedPropertyClientValidatorConfiguration {
    /**
     * Constraint name (i.e. NotNull).
     */
    name: string;
    /**
     * Constraint arguments as a map.
     */
    argumentMap: Record<string, unknown>;
    /**
     * Error message that should be shown if validation fails.
     */
    errorMessage: string;
}
interface ValidatorConverter {
    /**
     * Whether this ValidatorConverter supports conversion.
     * @param configuration configuration received from the server
     */
    supports(configuration: ConstrainedPropertyClientValidatorConfiguration): boolean;
    /**
     * Converts validation configuration to yup validator.
     * @param configuration configuration received from the server
     * @param validator yup validator
     */
    convert(configuration: ConstrainedPropertyClientValidatorConfiguration, validator: any): any;
}
interface FormConfigurationConfiguration {
    /**
     * Url where to fetch configuration from. It represents the part of the path till /fetch-all.
     */
    url?: string;
    /**
     * Additional configuration options to send with fetch request i.e. if some authentication information is required.
     */
    requestOptionsResolver?: () => RequestInit;
    /**
     * Additional converters to use for custom constraints.
     */
    additionalValidatorConverters?: ValidatorConverter[];
}

type FormConfigurationOptions = {
    /**
     * Array of current state form configurations.
     */
    formYupConfigurations: FormYupConfiguration[];
    /**
     * Flag that indicates weather form configuration is fetched from API.
     */
    formConfigurationLoaded: boolean;
    /**
     * Sets form configurations to state.
     * Use on initial call to find-all endpoint.
     * @param formConfigurations formConfigurations to set
     */
    set: (formConfigurations: FormYupConfiguration[]) => void;
    /**
     * Adds form configuration to state.
     * @param formConfiguration formConfiguration to add
     */
    add: (formConfiguration: FormYupConfiguration) => void;
    /**
     * Removes form configuration to state.
     * @param formConfiguration formConfiguration to add
     */
    remove: (formConfiguration: FormYupConfiguration) => void;
    /**
     * Sets form configuration loaded to state.
     * @param isLoaded loaded flag to set
     */
    setFormConfigurationLoaded: (formConfigurationLoaded: boolean) => void;
};
type UseFormConfiguration = () => FormConfigurationOptions;
/**
 * A hook which simplifies the usage of the form configuration state.
 * Uses the internal {@link useFormConfigurationStore} hook for managing the form configuration state.
 *
 * @returns An array of options to access and set the form configuration state and remove or add a single form configuration.
 */
declare const useFormConfiguration: UseFormConfiguration;
/**
 * A hook which extracts a specific Yup configuration from the form configuration identified by the form id.
 * Uses the internal {@link useFormConfigurationStore} hook for managing the form configuration state.
 *
 * @param formId Registered form id for a specific form configuration.
 *
 * @returns Mapped Yup configuration from the form configuration identified by the form id, or undefined if no matching form configuration is found.
 */
declare const useYupFormConfiguration: <T extends Record<string, any> = any>(formId: string) => ObjectSchema<T, yup.AnyObject, any, "">;

type Props = {
    /**
     * Content to show conditionally
     */
    children: React.ReactNode;
    /**
     * Custom loader to show until content loads
     */
    loader?: React.ReactNode;
} & FormConfigurationConfiguration;
/**
 * Should be used to wrap the whole app that includes forms, so it doesn't render them without loading form configuration from API first.
 * @param children content to show conditionally
 * @param loader custom loader to show until content loads
 */
declare const FormConfigurationProvider: ({ children, loader, ...fetchProps }: Props) => JSX.Element;

export { ConstrainedPropertyClientValidatorConfiguration, ConstrainedPropertyConfiguration, FormConfiguration, FormConfigurationConfiguration, FormConfigurationOptions, FormConfigurationProvider, FormYupConfiguration, Props, UseFormConfiguration, ValidatorConverter, useFormConfiguration, useYupFormConfiguration };
