'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

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; };

exports.default = Field;

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _reactIntl = require('react-intl');

var _immutable = require('immutable');

var _immutable2 = _interopRequireDefault(_immutable);

var _get = require('lodash/get');

var _get2 = _interopRequireDefault(_get);

var _warning = require('warning');

var _warning2 = _interopRequireDefault(_warning);

var _cspaceInput = require('cspace-input');

var _configHelpers = require('../../helpers/configHelpers');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var pathHelpers = _cspaceInput.helpers.pathHelpers;
var Label = _cspaceInput.components.Label;


var defaultViewConfigKey = 'view';

var renderLabel = function renderLabel(fieldDescriptor, recordData, props) {
  var fieldConfig = fieldDescriptor[_configHelpers.configKey];
  var message = (0, _get2.default)(fieldConfig, ['messages', 'name']);

  if (!message) {
    return null;
  }

  var configuredProps = {};

  if ('required' in fieldConfig) {
    configuredProps.required = (0, _configHelpers.isFieldRequired)(fieldDescriptor, recordData);
  }

  if ('readOnly' in fieldConfig) {
    configuredProps.readOnly = fieldConfig.readOnly;
  }

  return _react2.default.createElement(
    Label,
    _extends({}, props, configuredProps),
    _react2.default.createElement(_reactIntl.FormattedMessage, message)
  );
};

var propTypes = {
  viewType: _propTypes2.default.string,

  // Code in this component doesn't use these props, but the propTypes need to exist, because
  // users of this component may check for them to determine if those props should be passed.
  // We want to receive all the props that our base components may need, and then we'll handle
  // distributing them to the base components that accept them.

  /* eslint-disable react/no-unused-prop-types */
  name: _propTypes2.default.string,
  // The value prop will be validated by the base component, so allow anything here.
  value: _propTypes2.default.any,
  parentPath: _propTypes2.default.array,
  subpath: _propTypes2.default.string,
  label: _propTypes2.default.node,
  readOnly: _propTypes2.default.bool,
  onAddInstance: _propTypes2.default.func,
  onCommit: _propTypes2.default.func,
  onMoveInstance: _propTypes2.default.func,
  onRemoveInstance: _propTypes2.default.func,
  onSortInstances: _propTypes2.default.func
  /* eslint-enable react/no-unused-prop-types */
};

var contextTypes = {
  config: _propTypes2.default.object,
  intl: _reactIntl.intlShape,
  recordData: _propTypes2.default.instanceOf(_immutable2.default.Map),
  recordType: _propTypes2.default.string
};

function Field(props, context) {
  var config = context.config,
      intl = context.intl,
      recordData = context.recordData,
      recordType = context.recordType;
  var viewType = props.viewType;


  var fullPath = pathHelpers.getPath(props);

  // Filter out numeric parts of the path, since they indicate repeating instances that won't be
  // present in the field descriptor.

  var path = (0, _configHelpers.dataPathToFieldDescriptorPath)(fullPath);
  var fields = (0, _get2.default)(config, ['recordTypes', recordType, 'fields']);

  process.env.NODE_ENV !== 'production' ? (0, _warning2.default)(fields, 'No field descriptor found for the record type ' + recordType + '. The field with path ' + path + ' will not be rendered.') : void 0;

  if (!fields) {
    return null;
  }

  var field = (0, _get2.default)(fields, path);

  process.env.NODE_ENV !== 'production' ? (0, _warning2.default)(field, 'The path ' + path + ' is not present in the field descriptors for the record type ' + recordType + '. The field will not be rendered.') : void 0;

  if (!field) {
    return null;
  }

  var fieldConfig = field[_configHelpers.configKey];
  var viewConfigKey = viewType === 'search' ? 'searchView' : defaultViewConfigKey;
  var viewConfig = fieldConfig[viewConfigKey] || fieldConfig[defaultViewConfigKey];
  var BaseComponent = viewConfig.type;
  var configuredProps = viewConfig.props;
  var providedProps = {};

  var basePropTypes = BaseComponent.propTypes;

  Object.keys(props).forEach(function (propName) {
    if (propName in basePropTypes) {
      providedProps[propName] = props[propName];
    }
  });

  var computedProps = {};

  if (fieldConfig.repeating) {
    computedProps.repeating = fieldConfig.repeating;
  }

  if ('label' in basePropTypes) {
    computedProps.label = renderLabel(field, recordData, {
      readOnly: providedProps.readOnly
    });
  }

  if ('formatValue' in basePropTypes) {
    var valueMessage = (0, _get2.default)(fieldConfig, ['messages', 'value']);

    if (valueMessage) {
      computedProps.formatValue = function (value) {
        return intl.formatMessage(valueMessage, { value: value });
      };
    }
  }

  if ('renderChildInputLabel' in basePropTypes) {
    computedProps.renderChildInputLabel = function (childInput) {
      var childName = childInput.props.name;
      var childField = field[childName];

      return renderLabel(childField, recordData, {
        key: childName,
        readOnly: providedProps.readOnly
      });
    };
  }

  return _react2.default.createElement(BaseComponent, _extends({}, computedProps, providedProps, configuredProps));
}

Field.contextTypes = contextTypes;
Field.propTypes = propTypes;