'use strict';

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

export function isIndeterminate(checked) {
    return null === checked; // do not supply undefined
}

export class FormControl extends React.Component {
    static contextTypes = {
        form: PropTypes.object,
        getNeededAutoFocus: PropTypes.func,
        setNeededAutoFocus: PropTypes.func
    };

    static propTypes = {
        name: PropTypes.string.isRequired,
        hasFormGroupContainer: PropTypes.bool,
        hasFeedbackBlock: PropTypes.bool,
        testAutomationId: PropTypes.string
    };

    static defaultProps = {
        hasFormGroupContainer: false,
        hasFeedbackBlock: true,
        testAutomationId: null
    };

    componentDidUpdate() {
        const props = this.props;
        const context = this.context;
        const form = context.form;
        const isNeededAutoFocus =
            _.isFunction(context.getNeededAutoFocus) && context.getNeededAutoFocus();
        const hasError = form && props.name in form.value && !!form.errors[props.name];

        if (isNeededAutoFocus && hasError) {
            if (_.isFunction(context.setNeededAutoFocus)) {
                context.setNeededAutoFocus(false);
            }
            this.focus();
        }
    }

    getInputDOMNode() {
        return ReactDOM.findDOMNode(this.refs.input);
    }

    focus = () => {
        let node = this.getInputDOMNode();
        if (node) {
            node.focus();
        }
    };

    click() {
        let node = this.getInputDOMNode();
        if (node) {
            node.click();
        }
    }

    getValue() {
        let node = this.getInputDOMNode();
        if (node) {
            return node.value;
        }
        return null;
    }

    outputConverter(e) {
        return e && e.target ? e.target.value : e;
    }

    inputConverter(value) {
        return {value: value};
    }

    getPropsFromContext() {
        let props = this.props;
        let form = this.context.form;

        if (form && props.name in form.value) {
            let errors = form.errors[props.name];
            let showHelpBlock = errors && props.hasFeedbackBlock; //FIXME errors could be an array

            props = _.assign(
                {
                    help: showHelpBlock ? errors : null,
                    bsStyle: errors ? 'error' : undefined,
                    readOnly: form.readOnly,
                    onChange: e => form.setValue({[props.name]: this.outputConverter(e)})
                },
                this.inputConverter(form.value[props.name]),
                props
            );
        }

        return props;
    }

    /**
     * Removes FormGroup stuff from FormControl props
     * @param {object} props
     * @return {object}
     */
    getSafeProps(props) {
        const {
            label,
            validationState,
            bsStyle,
            controlId,
            controlLabel,
            help,
            hiddenLabel,
            labelClassName,
            wrapperClassName,
            groupClassName,
            hasFormGroupContainer,
            hasFeedbackBlock,
            readOnly,
            testAutomationId,
            isSingleSelect,
            minValue,
            maxValue,
            children,
            dangerouslySetInnerHTML,
            noOffset,
            ariaDescId,
            ariaLabelledById,
            ...rest
        } = props;
        return rest;
    }
}
