/* eslint-disable jsx-a11y/no-autofocus */
import React, { FC, forwardRef, memo, useState } from 'react';
import { cn }                                    from '../../util/bem';
import { FormSizesType, SizeType }               from '../../util/global-props';
import { Icon, IconPropsType }                   from '../icon/icon.component';
import { iconMap }                               from '../icon/icon.library';
import './input.component.scss';

export type InputPropsType = {
    className?: string;
    value?: string | typeof undefined;
    name?: string;
    placeholder?: string;

    icon?: keyof typeof iconMap;
    iconColor?: IconPropsType['color'];
    after?: React.ReactNode;
    before?: React.ReactNode;

    type?: 'text' | 'number' | 'password' | 'email';
    size?: FormSizesType;
    flex?: number;
    margin?: SizeType;

    autocompleteAttr?: string;
    clearable?: boolean;
    autoFocus?: boolean;
    autoComplete?: boolean;
    disabled?: boolean;
    fullWidth?: boolean;
    transparent?: boolean;
    readOnly?: boolean;
    required?: boolean;
    nativeProps?: React.InputHTMLAttributes<HTMLInputElement>;
    textCentered?: boolean;

    ref?: React.Ref<HTMLInputElement>;
    onChange?: React.ChangeEventHandler<HTMLInputElement>;
    onClick?: React.MouseEventHandler<HTMLInputElement>;
    onClear?: React.MouseEventHandler<HTMLButtonElement>;
    onFocus?: React.FocusEventHandler<HTMLInputElement>;
    onBlur?: React.FocusEventHandler<HTMLInputElement>;
    onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
    onKeyPress?: React.KeyboardEventHandler<HTMLInputElement>;
    onKeyUp?: React.KeyboardEventHandler<HTMLInputElement>;
}

const className = cn('input');

export const Input: FC<InputPropsType> = memo(forwardRef((props, ref: React.Ref<HTMLInputElement>) => {
    const [ focus, setFocus ] = useState(false);

    const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {
        setFocus(true);
        if (props.onFocus) {
            props.onFocus(event);
        }
    };
    const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
        setFocus(false);
        if (props.onBlur) {
            props.onBlur(event);
        }
    };

    return (
        <div
            className={ className({
                size:         props.size,
                fullWidth:    props.fullWidth,
                disabled:     props.disabled,
                transparent:  props.transparent,
                margin:       props.margin,
                focus,
                readOnly:     props.readOnly,
                textCentered: props.textCentered
            }, null, props.className) }
        >
            { props.icon && (
                <Icon name={ props.icon } color={ props.iconColor } />
            ) }

            { props.before && (
                <span className={ className('before') }>{ props.before }</span>
            ) }
            { /* @ts-ignore */ }
            <input
                type={ props.type }
                name={ props.name }
                value={ props.value }
                placeholder={ props.placeholder }

                ref={ ref }
                autoFocus={ props.autoFocus }
                disabled={ props.disabled }
                readOnly={ props.readOnly }
                autoComplete={ props.autoComplete ? 'On' : 'Off' }
                required={ props.required }

                onChange={ props.onChange }
                onClick={ props.onClick }
                onFocus={ handleFocus }
                onBlur={ handleBlur }
                onKeyDown={ props.onKeyDown }
                onKeyPress={ props.onKeyPress }
                onKeyUp={ props.onKeyUp }

                { ...props.nativeProps }
            />

            { props.clearable && (
                <span
                    className={ className('clear', { hidden: !props.value }) }
                    onClick={ props.onClear }
                >
                    <Icon name="close" color="grey" />
                </span>
            ) }

            { props.after && (
                <span className={ className('after') }>{ props.after }</span>
            ) }
        </div>
    );
}));

Input.defaultProps = {
    size:      'lg',
    type:      'text',
    iconColor: 'grey'
};
