var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Box } from 'grommet/es6/components/Box';
import { filterByFocusable } from 'grommet/es6/utils';

import { FormState } from './FormState';
import { StyledForm } from './StyledForm';

var styledComponents = {
  form: StyledForm
};

var Form = function (_Component) {
  _inherits(Form, _Component);

  function Form(props, context) {
    _classCallCheck(this, Form);

    var _this = _possibleConstructorReturn(this, _Component.call(this, props, context));

    _initialiseProps.call(_this);

    _this.config = {};
    var formState = new FormState(_this.config, props.object, function () {
      var errors = _this.state.errors;

      if (errors) {
        _this.setState({ errors: formState.getErrors() });
      } else {
        if (_this.props.onValidForm) {
          _this.props.onValidForm();
        }
        _this.setState({ data: formState.get() });
      }
      if (_this.props.onInvalidForm) {
        _this.props.onInvalidForm(!formState.isValid());
      }
    });
    _this.state = {
      config: {}, errors: undefined, submitted: false, formState: formState, data: formState.get()
    };
    return _this;
  }

  Form.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
    if (nextProps.object) {
      this.setState({ object: _extends({}, this.state.object, nextProps.object) });
    }
  };

  Form.prototype.componentDidMount = function componentDidMount() {
    var focusFirstChild = this.props.focusFirstChild;

    if (focusFirstChild) {
      var items = this.containerRef.getElementsByTagName('*');
      items = filterByFocusable(items);
      if (items.length > 0) {
        setTimeout(function () {
          items[0].focus();
        }, 0);
      }
    }
    this.state.formState.updateFields(this.config);
  };

  Form.prototype.getChildContext = function getChildContext() {
    return {
      form: {
        attachToForm: this.attachToForm,
        detachFromForm: this.detachFromForm,
        getFieldValue: this.getFieldValue,
        getFieldErrors: this.getFieldErrors,
        onFieldChange: this.updateObject
      }
    };
  };

  Form.prototype.render = function render() {
    var _this2 = this;

    var _props = this.props,
        children = _props.children,
        a11yTitle = _props.a11yTitle,
        onSubmitError = _props.onSubmitError,
        onValidForm = _props.onValidForm,
        onInvalidForm = _props.onInvalidForm,
        onSubmit = _props.onSubmit,
        tag = _props.tag,
        rest = _objectWithoutProperties(_props, ['children', 'a11yTitle', 'onSubmitError', 'onValidForm', 'onInvalidForm', 'onSubmit', 'tag']);

    var StyledComponent = styledComponents[tag];
    if (!StyledComponent) {
      StyledComponent = StyledForm.withComponent(tag);
      styledComponents[tag] = StyledComponent;
    }
    return React.createElement(
      StyledComponent,
      {
        onSubmit: this.onSubmit,
        'aria-label': a11yTitle
      },
      React.createElement(
        Box,
        { direction: 'row' },
        React.createElement(
          Box,
          rest,
          React.createElement(
            'div',
            { ref: function ref(_ref) {
                _this2.containerRef = _ref;
              } },
            children
          )
        )
      )
    );
  };

  return Form;
}(Component);

Form.childContextTypes = {
  form: PropTypes.object
};

var _initialiseProps = function _initialiseProps() {
  var _this3 = this;

  this.onSubmit = function (event) {
    var formState = _this3.state.formState;
    var _props2 = _this3.props,
        onSubmit = _props2.onSubmit,
        onSubmitError = _props2.onSubmitError;

    event.preventDefault();
    if (formState.isValid()) {
      _this3.setState({ errors: undefined });
      if (onSubmit) {
        onSubmit(formState.get());
      }
    } else {
      var errors = formState.getErrors();
      if (onSubmitError) {
        onSubmitError(errors);
      }
      _this3.setState({ errors: errors });
    }
  };

  this.updateObject = function (name, value) {
    _this3.state.data[name] = value;
  };

  this.attachToForm = function (name, props) {
    var _extends2;

    _this3.config = _extends({}, _this3.config, (_extends2 = {}, _extends2[name] = props, _extends2));
  };

  this.detachFromForm = function (name) {
    delete _this3.config[name];
  };

  this.getFieldValue = function (name) {
    return _this3.state.data[name];
  };

  this.getFieldErrors = function (name) {
    return _this3.state.errors ? _this3.state.errors[name] : null;
  };
};

Form.defaultProps = {
  focusFirstChild: true,
  onChange: undefined,
  onSubmit: undefined,
  onSubmitError: undefined,
  onInvalidForm: undefined,
  onValidForm: undefined,
  object: {},
  tag: 'form',
  basis: 'medium'
};

var FormDoc = void 0;
if (process.env.NODE_ENV !== 'production') {
  FormDoc = require('./doc').default(Form); // eslint-disable-line global-require
}

var FormWrapper = FormDoc || Form;

export { FormWrapper as Form };