import { StylableComponent } from '.'

/**
 * Every form field must have these props
 */
export interface AbstractFormField<T> {
    dirty: boolean
    focused: boolean
    valid: boolean
    errors: string[]
    required: boolean
    submitted?: boolean
    value: T
    asyncValue?: any
    loading?: boolean
}

/**
 * A FormHandler is a function that handles a form event
 * such as onChange, onFocus, onBlur etc.
 */
export type FormHandler<T> =
    (name: string, formName: string | undefined, field: AbstractFormField<T>) => any

/**
 * FormFieldProps are the props that a Redux container component
 * can expect to receive
 */
export interface FormFieldProps<T> extends StylableComponent {
    name: string
    formName?: string
    // If both a value isand an onChange handler are provided
    // then it is assumed that the client
    // will be controlling the component's value
    // however - the form reducer will also maintain
    // an up to date version of the value as well - so the value is not required
    value?: T
    asyncValue?: any
    required?: boolean
    disabled?: boolean
    placeholder?: string
    autofocus?: boolean
    validate?: FormHandler<T>
    asyncValidate?: FormHandler<T>
    onChange?: FormHandler<T>
    asyncOnChange?: FormHandler<T>
    onBlur?: FormHandler<T>
    onFocus?: FormHandler<T>
    options?: any[]
}

/**
 * FormFieldComponentProps are the props that the redux container
 * will pass on to its presentational component
 */
export interface FormFieldComponentProps<T> extends FormFieldProps<T> {
    field: AbstractFormField<T>
    setFormField: FormHandler<T>
}
