import { ArrayField } from '@effector-reform/core';
import { ArrayFieldItemType } from '@effector-reform/core';
import { ErrorsSchemaPayload } from '@effector-reform/core';
import { FieldError } from '@effector-reform/core';
import { FormErrors } from '@effector-reform/core';
import { FormEvent } from 'react';
import { FormType } from '@effector-reform/core';
import { FormValues } from '@effector-reform/core';
import { InsertOrReplacePayload } from '@effector-reform/core';
import { MovePayload } from '@effector-reform/core';
import { PartialRecursive } from '@effector-reform/core';
import { PrimitiveField } from '@effector-reform/core';
import { PrimitiveValue } from '@effector-reform/core';
import { PushPayload } from '@effector-reform/core';
import { ReadyFieldsGroupSchema } from '@effector-reform/core';
import { RemovePayload } from '@effector-reform/core';
import { StoreValue } from 'effector';
import { SwapPayload } from '@effector-reform/core';
import { UnshiftPayload } from '@effector-reform/core';

declare type AnyForm = FormType<any, any, any>;

export declare interface ReactArrayFieldApi<T extends ArrayFieldItemType, Meta extends object = any, Payload extends ArrayFieldItemType = T extends ReadyFieldsGroupSchema ? T | FormValues<T> : T> {
    values: (T extends ReadyFieldsGroupSchema ? ReactFields<T> : T)[];
    meta: Meta;
    error: FieldError;
    isValid: boolean;
    onChange: (values: Payload[]) => void;
    onChangeError: (error: FieldError) => void;
    onChangeMeta: (meta: Meta) => void;
    onReset: () => void;
    onPush: (payload: PushPayload<Payload>) => void;
    onSwap: (payload: SwapPayload) => void;
    onMove: (payload: MovePayload) => void;
    onInsert: (payload: InsertOrReplacePayload<Payload>) => void;
    onUnshift: (payload: UnshiftPayload<Payload>) => void;
    onRemove: (payload: RemovePayload) => void;
    onPop: (payload: void) => void;
    onReplace: (payload: InsertOrReplacePayload<Payload>) => void;
}

export declare type ReactFields<Fields extends ReadyFieldsGroupSchema> = {
    [K in keyof Fields]: Fields[K] extends PrimitiveField<any> ? ReactPrimitiveFieldApi<StoreValue<Fields[K]['$value']>, Fields[K] extends PrimitiveField<any, infer K> ? K : never> : Fields[K] extends ArrayField<any> ? ReactArrayFieldApi<StoreValue<Fields[K]['$values']>[number], Fields[K] extends ArrayField<any, infer K> ? K : never> : Fields[K] extends ReadyFieldsGroupSchema ? ReactFields<Fields[K]> : never;
};

declare type ReactForm<Schema extends ReadyFieldsGroupSchema, Values extends FormValues<any> = FormValues<Schema>, Errors extends FormErrors<any> = FormErrors<Schema>> = {
    values: Values;
    snapshot: Values;
    errors: Errors;
    fields: ReactFields<Schema>;
    onSubmit: (e: FormEvent<HTMLFormElement>) => void;
    onValidate: () => void;
    onReset: () => void;
    onClearOuterErrors: () => void;
    onClearInnerErrors: () => void;
    onForceUpdateSnapshot: () => void;
    isChanged: boolean;
    isValid: boolean;
    isValidationPending: boolean;
    fill: (data: {
        values?: PartialRecursive<Values>;
        errors?: ErrorsSchemaPayload;
    }) => void;
};

export declare interface ReactPrimitiveFieldApi<T extends PrimitiveValue, Meta extends object = any> {
    value: T;
    meta: Meta;
    error: FieldError;
    isValid: boolean;
    isFocused: boolean;
    onChangeError: (newError: FieldError) => void;
    onChange: (newValue: T) => void;
    onFocus: () => void;
    onBlur: () => void;
    onChangeMeta: (meta: Meta) => void;
}

export declare function useArrayField<T extends ArrayField<any>, Value extends ArrayFieldItemType = T extends ArrayField<any, any, infer D> ? D : never, Meta extends object = T extends ArrayField<any, infer D> ? D : any>(field: T): ReactArrayFieldApi<Value, Meta>;

export declare function useField<T extends PrimitiveValue, Meta extends object = any>(field: PrimitiveField<T, Meta>): ReactPrimitiveFieldApi<T, Meta>;

export declare function useForm<T extends AnyForm, Schema extends ReadyFieldsGroupSchema = T extends FormType<infer K, any, any> ? K : never, Values extends FormValues<any> = T extends FormType<any, infer K, any> ? K : never, Errors extends FormErrors<any> = T extends FormType<any, any, infer K> ? K : never>(form: T, props?: UseFormProps): ReactForm<Schema, Values, Errors>;

declare interface UseFormProps {
    resetOnUnmount?: boolean;
}

export { }
