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

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

function getSelectValues(select) {
    let result = [];
    let options = select && select.options;
    let opt;

    for (let i = 0; i < options.length; i++) {
        opt = options[i];

        if (opt.selected) {
            result.push(opt.value || opt.text);
        }
    }
    return result.length ? result : null;
}

@findParentForm
export default class Select extends Component {
    static displayName = 'FormElementSelect';

    get _formElement() {
        return true;
    }

    id = shortid();

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

    get _value() {
        if (this.props.multiple)
            return getSelectValues(this.input);
        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} = 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(value))
                } 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;
    }

    __onFocus() {
        this.setState({focus: true})
    }

    __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,
            mask,
            type,
        } = 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>}
            <div className="sbxFormField__control-wrapper">
                {props.htmlbefore ? props.htmlbefore : null}
                <select
                    {...props}
                    id={this.id}
                    ref={e => this.input = e}
                    onChange={this.__onChange}
                    onBlur={this.__onBlur}
                    className={classNames({
                        'sbxFormField__select': true,
                        'sbxFormField__select_invalid': error,
                        'sbxFormField__select_valid': success,
                        'sbxFormField__select_multiple': props.multiple,
                        [props.className]: !!props.className
                    })}
                >
                    {this.props.children}
                </select>
                {props.htmlafter ? props.htmlafter : null}
            </div>
            {error && <div
                className='sbxFormField__invalidFeedback'
            >
                {error}
            </div>}
        </div>
    }
}