import React, {Component} from 'react';
import shortid from 'shortid';
import MaskedInput, {conformToMask} from 'react-text-mask';
import classNames from 'classnames';

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

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



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

    get _formElement() {
        return true;
    }

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

    get input(){
        return this.__input.inputElement || this.__input
    }

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

    set(value) {
        if (this.props.mask) {
            value = conformToMask(
                value.toString(),
                this.props.mask,
                {
                    guide: false,
                    previousConformedValue: true
                }
            ).conformedValue;
        }
        this.input.value = value;
        if (this.props.onChange) {
            this.props.onChange(value);
        }
    }

    componentWillReceiveProps(nextProps) {
        if (this.props.value !== nextProps.value) {
            this.input.value = nextProps.value;
        }
    }

    componentDidMount() {
        if (this.props.value || this.props.value === 0) {
            this.input.value = this.props.value;
        }
    }

    validate() {
        let {_value: value} = this;
        let {validate, parentid, name} = this.props;
        let promises = [];
        let values = {};
        for(let field in store[parentid]){
            values[field] = store[parentid][field]._value;
        }
        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, values);
                } 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) {
        let {mask} = this.props;
        if (mask) {
            value = conformToMask(
                value + "",
                mask,
            );
            this.input.value = value.conformedValue;
        } else {
            this.input.value = value;
        }
    }

    __onFocus(e) {
        if(this.props.onFocus){
            this.props.onFocus(e);
        }
        this.setState({focus: true})
    }

    __onBlur = (e) => {
        if(this.props.onBlur){
            this.props.onBlur(e);
        }
        this.setState({focus: false});
        this.validate();
    };

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

    };

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

        let Input = mask ?  MaskedInput :'input';
        let props = {...this.props};
        delete props.value;
        delete props.validate;


        return <div className={classNames({
            'sbxFormField': true,
            'sbxFormField--error': error,
            'sbxFormField--focus': focus,
            'sbxFormField--value': value,
        })}>
            {label && <label
                htmlFor={this.id}
                className="sbxFormField__label"
            >
                {label}
            </label>}
            <div className="sbxFormField__control-wrapper">
                {props.htmlbefore ? props.htmlbefore : null}
                <Input
                    {...props}
                    id={this.id}
                    ref={e => this.__input = e}
                    onChange={this.__onChange}
                    onBlur={this.__onBlur.bind(this)}
                    onFocus={this.__onFocus.bind(this)}
                    className={classNames({
                        'sbxFormField__input': true,
                        'sbxFormField__input_invalid': error,
                        'sbxFormField__input_valid': success,
                        [props.className]: !!props.className
                    })}
                />
                {props.child&& props.child}
                {props.htmlafter ? props.htmlafter : null}
            </div>
            {error && <div
                className='sbxFormField__invalidFeedback'
            >
                {error}
            </div>}
        </div>
    }
}
