import _defineProperty from 'babel-runtime/helpers/defineProperty';
import _extends from 'babel-runtime/helpers/extends';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _createClass from 'babel-runtime/helpers/createClass';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Animate from 'rc-animate';
import PureRenderMixin from 'rc-util/es/PureRenderMixin';
import Row from '../grid/row';
import Col from '../grid/col';
import warning from '../_util/warning';
import { FIELD_META_PROP, FIELD_DATA_PROP } from './constants';

var FormItem = function (_React$Component) {
    _inherits(FormItem, _React$Component);

    function FormItem() {
        _classCallCheck(this, FormItem);

        // Resolve duplicated ids bug between different forms
        // https://github.com/ant-design/ant-design/issues/7351
        var _this = _possibleConstructorReturn(this, (FormItem.__proto__ || Object.getPrototypeOf(FormItem)).apply(this, arguments));

        _this.onLabelClick = function (e) {
            var id = _this.props.id || _this.getId();
            if (!id) {
                return;
            }
            var controls = document.querySelectorAll('[id="' + id + '"]');
            if (controls.length !== 1) {
                e.preventDefault();
                var control = ReactDOM.findDOMNode(_this).querySelector('[id="' + id + '"]');
                if (control && control.focus) {
                    control.focus();
                }
            }
        };
        return _this;
    }

    _createClass(FormItem, [{
        key: 'componentDidMount',
        value: function componentDidMount() {
            warning(this.getControls(this.props.children, true).length <= 1, '`Form.Item` cannot generate `validateStatus` and `help` automatically, ' + 'while there are more than one `getFieldDecorator` in it.');
        }
    }, {
        key: 'shouldComponentUpdate',
        value: function shouldComponentUpdate() {
            for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                args[_key] = arguments[_key];
            }

            return PureRenderMixin.shouldComponentUpdate.apply(this, args);
        }
    }, {
        key: 'getHelpMsg',
        value: function getHelpMsg() {
            var props = this.props;
            var onlyControl = this.getOnlyControl();
            if (props.help === undefined && onlyControl) {
                var errors = this.getField().errors;
                return errors ? errors.map(function (e) {
                    return e.message;
                }).join(', ') : '';
            }
            return props.help;
        }
    }, {
        key: 'getControls',
        value: function getControls(children, recursively) {
            var controls = [];
            var childrenArray = React.Children.toArray(children);
            for (var i = 0; i < childrenArray.length; i++) {
                if (!recursively && controls.length > 0) {
                    break;
                }
                var child = childrenArray[i];
                if (child.type && (child.type === FormItem || child.type.displayName === 'FormItem')) {
                    continue;
                }
                if (!child.props) {
                    continue;
                }
                if (FIELD_META_PROP in child.props) {
                    controls.push(child);
                } else if (child.props.children) {
                    controls = controls.concat(this.getControls(child.props.children, recursively));
                }
            }
            return controls;
        }
    }, {
        key: 'getOnlyControl',
        value: function getOnlyControl() {
            var child = this.getControls(this.props.children, false)[0];
            return child !== undefined ? child : null;
        }
    }, {
        key: 'getChildProp',
        value: function getChildProp(prop) {
            var child = this.getOnlyControl();
            return child && child.props && child.props[prop];
        }
    }, {
        key: 'getId',
        value: function getId() {
            return this.getChildProp('id');
        }
    }, {
        key: 'getMeta',
        value: function getMeta() {
            return this.getChildProp(FIELD_META_PROP);
        }
    }, {
        key: 'getField',
        value: function getField() {
            return this.getChildProp(FIELD_DATA_PROP);
        }
    }, {
        key: 'renderHelp',
        value: function renderHelp() {
            var prefixCls = this.props.prefixCls;
            var help = this.getHelpMsg();
            var children = help ? React.createElement(
                'div',
                { className: prefixCls + '-explain', key: 'help' },
                help
            ) : null;
            return React.createElement(
                Animate,
                { transitionName: 'show-help', component: '', transitionAppear: true, key: 'help' },
                children
            );
        }
    }, {
        key: 'renderExtra',
        value: function renderExtra() {
            var _props = this.props,
                prefixCls = _props.prefixCls,
                extra = _props.extra;

            return extra ? React.createElement(
                'div',
                { className: prefixCls + '-extra' },
                extra
            ) : null;
        }
    }, {
        key: 'getValidateStatus',
        value: function getValidateStatus() {
            var onlyControl = this.getOnlyControl();
            if (!onlyControl) {
                return '';
            }
            var field = this.getField();
            if (field.validating) {
                return 'validating';
            }
            if (field.errors) {
                return 'error';
            }
            var fieldValue = 'value' in field ? field.value : this.getMeta().initialValue;
            if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {
                return 'success';
            }
            return '';
        }
    }, {
        key: 'renderValidateWrapper',
        value: function renderValidateWrapper(c1, c2, c3) {
            var props = this.props;
            var onlyControl = this.getOnlyControl;
            var validateStatus = props.validateStatus === undefined && onlyControl ? this.getValidateStatus() : props.validateStatus;
            var classes = '';
            if (validateStatus) {
                classes = classNames({
                    'has-feedback': props.hasFeedback || validateStatus === 'validating',
                    'has-success': validateStatus === 'success',
                    'has-warning': validateStatus === 'warning',
                    'has-error': validateStatus === 'error',
                    'is-validating': validateStatus === 'validating'
                });
            }
            return React.createElement(
                'div',
                { className: this.props.prefixCls + '-item-control ' + classes },
                c1,
                c2,
                c3
            );
        }
    }, {
        key: 'renderWrapper',
        value: function renderWrapper(children) {
            var _props2 = this.props,
                prefixCls = _props2.prefixCls,
                wrapperCol = _props2.wrapperCol;

            var className = classNames(prefixCls + '-item-control-wrapper', wrapperCol && wrapperCol.className);
            return React.createElement(
                Col,
                _extends({}, wrapperCol, { className: className, key: 'wrapper' }),
                children
            );
        }
    }, {
        key: 'isRequired',
        value: function isRequired() {
            var required = this.props.required;

            if (required !== undefined) {
                return required;
            }
            if (this.getOnlyControl()) {
                var meta = this.getMeta() || {};
                var validate = meta.validate || [];
                return validate.filter(function (item) {
                    return !!item.rules;
                }).some(function (item) {
                    return item.rules.some(function (rule) {
                        return rule.required;
                    });
                });
            }
            return false;
        }
    }, {
        key: 'renderLabel',
        value: function renderLabel() {
            var _props3 = this.props,
                prefixCls = _props3.prefixCls,
                label = _props3.label,
                labelCol = _props3.labelCol,
                colon = _props3.colon,
                id = _props3.id;

            var context = this.context;
            var required = this.isRequired();
            var labelColClassName = classNames(prefixCls + '-item-label', labelCol && labelCol.className);
            var labelClassName = classNames(_defineProperty({}, prefixCls + '-item-required', required));
            var labelChildren = label;
            // Keep label is original where there should have no colon
            var haveColon = colon && !context.vertical;
            // Remove duplicated user input colon
            if (haveColon && typeof label === 'string' && label.trim() !== '') {
                labelChildren = label.replace(/[：|:]\s*$/, '');
            }
            return label ? React.createElement(
                Col,
                _extends({}, labelCol, { className: labelColClassName, key: 'label' }),
                React.createElement(
                    'label',
                    { htmlFor: id || this.getId(), className: labelClassName, title: typeof label === 'string' ? label : '', onClick: this.onLabelClick },
                    labelChildren
                )
            ) : null;
        }
    }, {
        key: 'renderChildren',
        value: function renderChildren() {
            var children = this.props.children;

            return [this.renderLabel(), this.renderWrapper(this.renderValidateWrapper(children, this.renderHelp(), this.renderExtra()))];
        }
    }, {
        key: 'renderFormItem',
        value: function renderFormItem(children) {
            var _itemClassName;

            var props = this.props;
            var prefixCls = props.prefixCls;
            var style = props.style;
            var itemClassName = (_itemClassName = {}, _defineProperty(_itemClassName, prefixCls + '-item', true), _defineProperty(_itemClassName, prefixCls + '-item-with-help', !!this.getHelpMsg()), _defineProperty(_itemClassName, prefixCls + '-item-no-colon', !props.colon), _defineProperty(_itemClassName, '' + props.className, !!props.className), _itemClassName);
            return React.createElement(
                Row,
                { className: classNames(itemClassName), style: style },
                children
            );
        }
    }, {
        key: 'render',
        value: function render() {
            var children = this.renderChildren();
            return this.renderFormItem(children);
        }
    }]);

    return FormItem;
}(React.Component);

export default FormItem;

FormItem.defaultProps = {
    hasFeedback: false,
    prefixCls: 'ant-form',
    colon: true
};
FormItem.propTypes = {
    prefixCls: PropTypes.string,
    label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
    labelCol: PropTypes.object,
    help: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]),
    validateStatus: PropTypes.oneOf(['', 'success', 'warning', 'error', 'validating']),
    hasFeedback: PropTypes.bool,
    wrapperCol: PropTypes.object,
    className: PropTypes.string,
    id: PropTypes.string,
    children: PropTypes.node,
    colon: PropTypes.bool
};
FormItem.contextTypes = {
    vertical: PropTypes.bool
};