import _objectSpread from "@babel/runtime/helpers/esm/objectSpread";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from './FormContext';
import render from './fieldRender';
/**
 * Field
 * @ignore
 */

var Field =
/*#__PURE__*/
function (_Component) {
  _inherits(Field, _Component);

  function Field(props) {
    var _this;

    _classCallCheck(this, Field);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(Field).call(this, props));

    _defineProperty(_assertThisInitialized(_this), "handleChangeAndValidate", function (e, value) {
      var _this$props = _this.props,
          name = _this$props.name,
          onFieldChange = _this$props.onFieldChange,
          validateItem = _this$props.validateItem,
          trigger = _this$props.trigger,
          onValidate = _this$props.onValidate,
          options = _this$props.options,
          onTrigger = _this$props[trigger];

      var formattedValue = _this.format(e, value, name);

      onFieldChange(formattedValue);
      var result = validateItem(name, formattedValue[name], _assertThisInitialized(_this), options);
      if (result) result.then(onValidate, onValidate);

      if (onTrigger) {
        for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
          args[_key - 2] = arguments[_key];
        }

        onTrigger.apply(void 0, [e, value].concat(args));
      }

      return result;
    });

    _defineProperty(_assertThisInitialized(_this), "handleValueChange", function (e, value) {
      var _this$props2 = _this.props,
          name = _this$props2.name,
          onFieldChange = _this$props2.onFieldChange,
          trigger = _this$props2.trigger,
          onTrigger = _this$props2[trigger];

      var formattedValue = _this.format(e, value, name);

      onFieldChange(formattedValue);

      if (onTrigger) {
        for (var _len2 = arguments.length, args = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
          args[_key2 - 2] = arguments[_key2];
        }

        onTrigger.apply(void 0, [e, value].concat(args));
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleValidate", function (e, value) {
      var result;
      var _this$props3 = _this.props,
          name = _this$props3.name,
          validateItem = _this$props3.validateItem,
          onValidate = _this$props3.onValidate,
          options = _this$props3.options,
          validateTrigger = _this$props3.validateTrigger,
          onTrigger = _this$props3[validateTrigger];

      if (!e) {
        result = validateItem(name, null, _assertThisInitialized(_this), options);
      } else {
        var formattedValue = _this.format(e, value, name);

        result = validateItem(name, formattedValue[name], _assertThisInitialized(_this), options);
      }

      if (result) result.then(onValidate, onValidate);

      if (onTrigger) {
        for (var _len3 = arguments.length, args = new Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
          args[_key3 - 2] = arguments[_key3];
        }

        onTrigger.apply(void 0, [e, value].concat(args));
      }

      return result;
    });

    var register = props.register,
        _name = props.name;

    if (!register) {
      console.warn('Field must be inside a component decorated with createForm()');
    }

    if (register && _name != null) {
      register(_name, _assertThisInitialized(_this));
    }

    return _this;
  }

  _createClass(Field, [{
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps) {
      var _this$props4 = this.props,
          name = _this$props4.name,
          register = _this$props4.register,
          unRegister = _this$props4.unRegister;

      if (name !== prevProps.name && prevProps.name != null) {
        unRegister(prevProps.name);
        register(name, this);
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      var _this$props5 = this.props,
          unRegister = _this$props5.unRegister,
          name = _this$props5.name;

      if (unRegister && name) {
        unRegister(name);
      }
    }
  }, {
    key: "getValueFromEvent",
    value: function getValueFromEvent(e, value) {
      var newValue;
      var _this$props6 = this.props,
          valuePropName = _this$props6.valuePropName,
          getValueFromEvent = _this$props6.getValueFromEvent;

      if (getValueFromEvent) {
        for (var _len4 = arguments.length, other = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) {
          other[_key4 - 2] = arguments[_key4];
        }

        return getValueFromEvent.apply(void 0, [e, value].concat(other));
      }

      if (!e) {
        return e;
      }

      if (!e.target && !e.preventDefault) {
        newValue = e;
      } else if (value != null) {
        newValue = value;
      } else if (e.target[valuePropName] != null) {
        newValue = e.target[valuePropName];
      } else {
        newValue = e.target.value;
      }

      return newValue;
    }
  }, {
    key: "format",
    value: function format(e, oldValue, name) {
      var formatter = this.props.formatter;
      var value = this.getValueFromEvent(e, oldValue);
      var formattedValue = formatter ? formatter(value) : value;
      return _defineProperty({}, name, formattedValue);
    }
  }, {
    key: "render",
    value: function render() {
      var _this$props7 = this.props,
          defaultValue = _this$props7.defaultValue,
          values = _this$props7.values,
          errors = _this$props7.errors,
          error = _this$props7.error,
          validatings = _this$props7.validatings,
          validating = _this$props7.validating,
          name = _this$props7.name,
          render = _this$props7.render,
          validateTrigger = _this$props7.validateTrigger,
          valuePropName = _this$props7.valuePropName,
          trigger = _this$props7.trigger,
          statusProps = _this$props7.status,
          other = _objectWithoutProperties(_this$props7, ["defaultValue", "values", "errors", "error", "validatings", "validating", "name", "render", "validateTrigger", "valuePropName", "trigger", "status"]);

      var dataBindProps = {};

      if (name != null) {
        dataBindProps[valuePropName] = values[name];
        dataBindProps[trigger] = this.handleValueChange;
      }

      if (validateTrigger !== 'ignore' && name) {
        dataBindProps[validateTrigger] = validateTrigger === trigger ? this.handleChangeAndValidate : this.handleValidate;
      }

      var status;

      if (name == null) {
        status = statusProps;
      } else if (validatings[name]) {
        status = 'validating';
      } else if (errors[name] && errors[name].length > 0) {
        status = 'error';
      } else if (errors[name] && errors[name].length === 0) {
        status = 'success';
      }

      return render(_objectSpread({}, other, {
        id: "easy-form-".concat(name || Math.floor(Math.random() * 10000)),
        name: name,
        dataBindProps: dataBindProps,
        trigger: trigger,
        status: status,
        onValidate: this.handleValidate,
        onValueChange: this.handleValueChange,
        onValueChangeAndValidate: this.handleChangeAndValidate,
        error: name ? errors[name] : error,
        validating: name ? validatings[name] : status === 'validating'
      }));
    }
  }]);

  return Field;
}(Component);

_defineProperty(Field, "propTypes", {
  /**
   * Prop that should be validated. For example, the `valuePropName` of checkbox is `checked`.
   */
  valuePropName: PropTypes.string,

  /**
   * When to validate the value of children node.
   */
  validateTrigger: PropTypes.string,

  /**
   * When to collect the value of children node.
   */
  trigger: PropTypes.string,

  /**
   * The unique identifier of field, corresponding to a value in the form values.
   */
  name: PropTypes.string.isRequired,

  /**
   * @ignore
   */
  defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),

  /**
   * Callback fired after validation.
   * @param {object} result The result of validation.
   * You can pull out the return of the validator by accessing `result.promiseValue`.
   */
  onValidate: PropTypes.func,

  /**
   * Handler that format the input.
   * @param {string | boolean | number} value The value of input.
   * @returns {object} The formatted value.
   */
  formatter: PropTypes.func,

  /**
   * Render Props.
   * @param {object} props Please refer to `fieldRender`.
   * @returns {object} The React node to be rendered.
   */
  render: PropTypes.func.isRequired
});

_defineProperty(Field, "defaultProps", {
  valuePropName: 'value',
  validateTrigger: 'onChange',
  trigger: 'onChange',
  render: render,
  size: 'medium',
  defaultValue: ''
});

export default connect(Field);