import React from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../tools/namingTools';
import { TEXT, NUMBER, EMAIL, TEL, SEARCH } from '../../constants/inputTypes';
import FormLabel from '../form-label/FormLabel';

import './styles/Input.scss';
import { generateUniqueID } from '../../tools/helpers';

const n = createNamespace('Input');
const inputTypes = [TEXT, NUMBER, EMAIL, TEL, SEARCH];

const Input = ({
    type,
    name,
    label,
    error,
    inputRef,
    hiddenLabel,
    required,
    placeholder,
    hint,
    addon,
    addonLabel,
    defaultValue,
    className: extraClass,
    i18n,
    ...otherProps
}) => {
    const inputType = inputTypes.includes(type) ? type : TEXT;

    const controlModifier = [
        type,
        addon && 'with-addon',
        error && 'error'
    ];
    const labelTextModifier = hiddenLabel ? 'hidden' : null;
    const errorId = generateUniqueID(['error', name]);

    const renderInput = (
        <input
            id={name}
            type={inputType}
            name={name}
            ref={inputRef}
            placeholder={placeholder}
            defaultValue={defaultValue}
            required={required}
            aria-invalid={Boolean(error)}
            aria-describedby={Boolean(error) && errorId}
            {...otherProps}
            {...n('control', controlModifier).withClass(extraClass).withTestId().props}
        />
    );

    return (
        <div {...n('group').props}>
            <FormLabel
                labelText={label}
                required={required}
                labelProps={n('label').withTestId().props}
                htmlFor={name}
                i18n={i18n}
                textProps={n('text', labelTextModifier).withTestId().props}
            >
                {addon ? (
                    <span {...n('controlWrapper', controlModifier).props}>
                        <span {...n('addon').withTestId().props} aria-label={addonLabel}>{addon}</span>
                        {renderInput}
                    </span>
                ) : renderInput}
            </FormLabel>
            {hint && (
                <span {...n('hint').props}>{hint}</span>
            )}
            {error && (
                <span {...n('error').withTestId().props} aria-live="polite" id={errorId}>
                    {error}
                </span>
            )}
        </div>
    );
};

Input.propTypes = {
    type: PropTypes.oneOf(inputTypes),
    name: PropTypes.string.isRequired,
    label: PropTypes.string,
    error: PropTypes.string,
    required: PropTypes.bool,
    defaultValue: PropTypes.string,
    placeholder: PropTypes.string,
    hint: PropTypes.string,
    addon: PropTypes.string,
    addonLabel: PropTypes.string,
    inputRef: PropTypes.func,
    hiddenLabel: PropTypes.bool,
    className: PropTypes.string,
    i18n: PropTypes.shape({
        fieldRequired: PropTypes.string
    })
};

Input.defaultProps = {
    type: TEXT,
    label: '',
    error: null,
    inputRef: null,
    required: false,
    defaultValue: '',
    placeholder: null,
    hint: null,
    addon: null,
    hiddenLabel: false,
    className: null,
    addonLabel: null,
    i18n: null
};

export default Input;
