import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';

import './index.styl';

const IGNORED_HTML_INPUT_PROPS = [
    'suffix', 'placeholderLabel', 'tip', 'tipPosition', 'error',
    'size', 'border', 'width', 'valid', 'clearable',
];

const Input = React.createClass({

    _name: 'lego-input',

    getInitialState() {
        return {};
    },

    focus() {
        // событие focus не отрабатывает на только что созданных инпутах,
        // поэтому устанавливаем фокус с минимальной задержкой
        setTimeout(() => this._input && this._input.focus(), 0);
    },

    getValue() {
        if (this._input) {
            return this._input.value;
        }
    },

    _initialize(element) {
        this._input = element;
    },

    _onClick() {
        this.focus();
    },

    _onFocus(event) {
        const { onFocus } = this.props;

        this.setState({ focused: true });

        if (onFocus) {
            onFocus(event);
        }
    },

    _onBlur(event) {
        const { onBlur } = this.props;

        this.setState({ focused: false });

        if (onBlur) {
            onBlur(event);
        }
    },

    _onClear() {
        this._input.value = '';

        ['onInput', 'onKeyDown'].forEach(key => {
            if (this.props[key] && this._input) {
                this.props[key]({ target: this._input });
            }
        });
    },

    _adjust(element) {
        if (!element) {
            return;
        }

        const subcontainer = element.querySelector(`${this._name}__subcontainer`);
        const suffix = element.querySelector(`${this._name}__suffix`);

        if (subcontainer && suffix) {
            subcontainer.style.marginRight = `${suffix.offsetWidth}px`;
        }
    },

    render() {
        const component = {};

        const className = [
            `${this._name}__container`,
            this.props.placeholderLabel ? `${this._name}_labeled` : null,
            this.props.error || this.props.valid === false ? `${this._name}_invalid` : null,
            `${this._name}_size-${this.props.size}`,
            `${this._name}_border-${this.props.border}`,
            this.state.focused ? `${this._name}_focused` : null,
            this.props.disabled ? `${this._name}_disabled` : null,
            this.props.width === 'available' ? `${this._name}_full-width` : null,
        ].filter(Boolean).join(' ');

        if (this.props.clearable) {
            component.clear =
                <span className={`${this._name}__clear`} onClick={this._onClear} />;
        }

        ['suffix', 'placeholderLabel'].forEach(key => {
            if (this.props[key]) {
                component[key] = (
                    <span className={`${this._name}__${_.kebabCase(key)}`}>
                        {this.props[key]}
                    </span>
                );
            }
        });

        if (this.props.error || this.props.tip) {
            component.tip = (
                <span className={`${this._name}__tip ${this._name}__tip_${this.props.tipPosition}`}>
                    <span dangerouslySetInnerHTML={{ __html: this.props.error || this.props.tip }} />
                </span>
            );
        }

        return (
            <span
                className={className}
                onClick={this._onClick}
                ref={this._adjust}
                aria-live="off"
            >
                <span className={`${this._name}__subcontainer`}>
                    <input
                        autoComplete="off"
                        {..._.omit(this.props, IGNORED_HTML_INPUT_PROPS)}
                        className={this._name}
                        ref={this._initialize}
                        onFocus={this._onFocus}
                        onBlur={this._onBlur}
                    />
                    {component.placeholderLabel}
                    {component.clear}
                </span>
                {component.suffix}
                {component.tip}
            </span>
        );
    },

});

// @if NODE_ENV='development'
Input.propTypes = {
    suffix: PropTypes.string,
    border: PropTypes.oneOf(['none', 'all', 'bottom']),
    tipPosition: PropTypes.oneOf(['right', 'bottom', 'bottom-left']),
};
// @endif

Input.defaultProps = {
    type: 'text',
    size: 'm',
    border: 'all',
    tipPosition: 'right',
    // чтобы пользоваться css-псевдоклассом :placeholder-shown, который соответствует
    // элементам с пустым полем ввода, добавляем пустой плейсхолдер по умолчанию;
    // вебкит не применяет псевдокласс :placeholder-shown с пустой строкой
    // в плейсхолдере, поэтому ставим не влияющий на отображение пробел
    placeholder: ' ',
};

export default Input;
