import React, {Component} from 'react';
import shortid from 'shortid';
import classNames from 'classnames';

import {validations, getValidator} from '../../helpers/helpers';

import findParentForm from '../../helpers/findParentForm';


@findParentForm
export default class Input extends Component {
    id = shortid();

    state = {
        focus: false,
        error: null,
        success: null,
        value: this.props.value
    };

    get _value() {
        return this.input.value;
    }

    set(value) {
        this.input.value = value;
        if (this.props.onChange) {
            this.props.onChange(value);
        }
    }

    componentDidUpdate(prevProps) {
        if (this.props.value !== prevProps.value) {
            this.input.value = this.props.value;
        }
    }

    validate() {
        let {_value: value} = this;
        let {validate} = this.props;
        let promises = [];
        if (!validate) {
            this.setState({success: true, error: null});
            return Promise.resolve(value);
        } else if ({}.toString.call(validate) === '[object Function]') {
            promises.push(validate(value));
        } else {
            for (let key in validate) {
                let valid = null;
                let error = validate[key].error || 'ERROR';
                if (validate[key].custom) {
                    valid = validate[key].custom(value);
                } else {
                    let validator = getValidator(key);
                    valid = validations[validator.name](value, ...validator.args);
                }
                if (valid) {
                    promises.push(Promise.resolve())
                } else {
                    promises.push(Promise.reject(error));
                    break;
                }
            }
        }
        return Promise.all(promises).then(() => {
            this.setState({success: true, error: null});
            return Promise.resolve(value);
        }).catch((error) => {
            this.setState({success: null, error});
            return Promise.reject(error);
        })
    }

    __setValue(value) {
        this.input.value = value;
    }

    __onBlur = (e) => {
        if(this.props.onBlur){
            this.props.onBlur(e);
        }
        this.validate();
    };

    __onChange = (e) => {
        let {onChange} = this.props;
        if (onChange) {
            onChange(e.target.value);
        }
        this.validate();

    };

    render() {
        let {error, success} = this.state;
        let {
            label,
            validate,
            value: defaultValue
        } = this.props;
        const isRequired = !!validate && !!validate['isRequired'];

        let props = {...this.props};

        delete props.validate;
        delete props.children;
        delete props.value;


        return <div className="sbxFormField">
            {label && <label
                htmlFor={this.id}
                className="sbxFormField__label"
            >
                {label}
            </label>}
            <textarea
                {...props}
                id={this.id}
                defaultValue={defaultValue}
                ref={e => this.input = e}
                onChange={this.__onChange}
                onBlur={this.__onBlur}
                className={classNames({
                    'sbxFormField__textarea': true,
                    'sbxFormField__input': true,
                    'sbxFormField__input_invalid': error,
                    'sbxFormField__input_valid': success,
                    [props.className]: !!props.className
                })}
            >
            </textarea>
            {error && <div
                className='sbxFormField__invalidFeedback'
            >
                {error}
            </div>}
        </div>
    }
}