'use strict';

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

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

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 _cspaceRefname = require('cspace-refname');

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

var _cspaceLayout = require('cspace-layout');

var _HierarchySiblingListContainer = require('../../containers/record/HierarchySiblingListContainer');

var _HierarchySiblingListContainer2 = _interopRequireDefault(_HierarchySiblingListContainer);

var _HierarchyReparentNotifierContainer = require('../../containers/record/HierarchyReparentNotifierContainer');

var _HierarchyReparentNotifierContainer2 = _interopRequireDefault(_HierarchyReparentNotifierContainer);

var _UntypedHierarchyEditor = require('./UntypedHierarchyEditor');

var _UntypedHierarchyEditor2 = _interopRequireDefault(_UntypedHierarchyEditor);

var _TypedHierarchyEditor = require('./TypedHierarchyEditor');

var _TypedHierarchyEditor2 = _interopRequireDefault(_TypedHierarchyEditor);

var _relationListHelpers = require('../../../src/helpers/relationListHelpers');

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

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

var _inputHelpers$pathHel = _cspaceInput.helpers.pathHelpers,
    getPath = _inputHelpers$pathHel.getPath,
    pathPropType = _inputHelpers$pathHel.pathPropType;


var findParent = function findParent(csid, relations) {
  var broaderRelation = (0, _relationListHelpers.findBroaderRelation)(csid, relations);

  if (broaderRelation) {
    return _immutable2.default.Map({
      relCsid: broaderRelation.get('csid'),
      csid: broaderRelation.getIn(['object', 'csid']),
      refName: broaderRelation.getIn(['object', 'refName']),
      type: broaderRelation.get('relationshipMetaType')
    });
  }

  return null;
};

var findChildren = function findChildren(csid, relations) {
  return (0, _relationListHelpers.findNarrowerRelations)(csid, relations).sort(function (relationA, relationB) {
    var displayNameA = (0, _cspaceRefname.getDisplayName)(relationA.getIn(['subject', 'refName']));
    var displayNameB = (0, _cspaceRefname.getDisplayName)(relationB.getIn(['subject', 'refName']));

    if (displayNameA && displayNameB) {
      return displayNameA.localeCompare(displayNameB);
    }

    if (!displayNameA && !displayNameB) {
      return 0;
    }

    if (displayNameA) {
      return -1;
    }

    return 1;
  }).map(function (relation) {
    return _immutable2.default.Map({
      relCsid: relation.get('csid'),
      refName: relation.getIn(['subject', 'refName']),
      type: relation.get('relationshipMetaType')
    });
  });
};

var propTypes = {
  csid: _propTypes2.default.string,
  messages: _propTypes2.default.object,
  /* eslint-disable react/no-unused-prop-types */
  name: _propTypes2.default.string,
  parentPath: pathPropType,
  subpath: pathPropType,
  readOnly: _propTypes2.default.bool,
  /* eslint-enable react/no-unused-prop-types */
  showParent: _propTypes2.default.bool,
  showChildren: _propTypes2.default.bool,
  showSiblings: _propTypes2.default.bool,
  value: _propTypes2.default.oneOfType([_propTypes2.default.instanceOf(_immutable2.default.List), _propTypes2.default.instanceOf(_immutable2.default.Map), _propTypes2.default.array, _propTypes2.default.object]),
  parentTypeOptionListName: _propTypes2.default.string,
  childTypeOptionListName: _propTypes2.default.string,
  onCommit: _propTypes2.default.func
};

var defaultProps = {
  showParent: true,
  showChildren: true,
  showSiblings: true
};

var contextTypes = {
  config: _propTypes2.default.object,
  recordType: _propTypes2.default.string,
  vocabulary: _propTypes2.default.string
};

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

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

    var _this = _possibleConstructorReturn(this, (HierarchyInput.__proto__ || Object.getPrototypeOf(HierarchyInput)).call(this));

    _this.handleAddChild = _this.handleAddChild.bind(_this);
    _this.handleRemoveChild = _this.handleRemoveChild.bind(_this);
    _this.handleCommit = _this.handleCommit.bind(_this);
    return _this;
  }

  _createClass(HierarchyInput, [{
    key: 'componentWillMount',
    value: function componentWillMount() {
      var _props = this.props,
          csid = _props.csid,
          value = _props.value;


      this.initHierarchy(csid, value);
    }
  }, {
    key: 'componentWillUpdate',
    value: function componentWillUpdate(nextProps) {
      var _props2 = this.props,
          csid = _props2.csid,
          value = _props2.value;
      var nextCsid = nextProps.csid,
          nextValue = nextProps.value;


      if (nextCsid !== csid || nextValue !== value) {
        this.initHierarchy(nextCsid, nextValue);
      }
    }
  }, {
    key: 'getRelationItems',
    value: function getRelationItems(hierarchy) {
      var csid = this.props.csid;


      var children = hierarchy.get('children');

      var childRelationItems = children.map(function (child) {
        return _immutable2.default.fromJS({
          csid: child.get('relCsid'),
          predicate: 'hasBroader',
          relationshipMetaType: child.get('type'),
          subject: {
            refName: child.get('refName')
          },
          object: {
            csid: csid || _relationListHelpers.placeholderCsid
          }
        });
      });

      var parent = hierarchy.get('parent');

      var parentRelationItem = _immutable2.default.fromJS({
        csid: parent.get('relCsid'),
        predicate: 'hasBroader',
        relationshipMetaType: parent.get('type'),
        subject: {
          csid: csid || _relationListHelpers.placeholderCsid
        },
        object: {
          csid: parent.get('csid'),
          refName: parent.get('refName')
        }
      });

      return childRelationItems.push(parentRelationItem);
    }
  }, {
    key: 'initHierarchy',
    value: function initHierarchy(csid, value) {
      var relations = (0, _relationListHelpers.normalizeRelationList)(value);

      var hierarchy = _immutable2.default.fromJS({
        parent: findParent(csid, relations) || _immutable2.default.Map(),
        children: findChildren(csid, relations)
      });

      this.setState({
        hierarchy: hierarchy
      });
    }
  }, {
    key: 'handleAddChild',
    value: function handleAddChild() {
      var onCommit = this.props.onCommit;


      if (onCommit) {
        var hierarchy = this.state.hierarchy;


        var children = hierarchy.get('children');
        var updatedHierarchy = hierarchy.set('children', children.push(_immutable2.default.Map()));

        onCommit(getPath(this.props), this.getRelationItems(updatedHierarchy));
      }
    }
  }, {
    key: 'handleRemoveChild',
    value: function handleRemoveChild(position) {
      var onCommit = this.props.onCommit;


      if (onCommit) {
        var hierarchy = this.state.hierarchy;


        var children = hierarchy.get('children');
        var updatedHierarchy = hierarchy.set('children', children.delete(position));

        onCommit(getPath(this.props), this.getRelationItems(updatedHierarchy));
      }
    }
  }, {
    key: 'handleCommit',
    value: function handleCommit(path, value) {
      var onCommit = this.props.onCommit;


      if (onCommit) {
        var hierarchy = this.state.hierarchy;


        var updatedHierarchy = hierarchy.setIn(path, value);

        onCommit(getPath(this.props), this.getRelationItems(updatedHierarchy));
      }
    }
  }, {
    key: 'renderHierarchy',
    value: function renderHierarchy() {
      var _props3 = this.props,
          csid = _props3.csid,
          messages = _props3.messages,
          parentTypeOptionListName = _props3.parentTypeOptionListName,
          childTypeOptionListName = _props3.childTypeOptionListName,
          readOnly = _props3.readOnly,
          showParent = _props3.showParent,
          showChildren = _props3.showChildren;


      if (!showParent && !showChildren) {
        return undefined;
      }

      var _context = this.context,
          config = _context.config,
          recordType = _context.recordType,
          vocabulary = _context.vocabulary;
      var hierarchy = this.state.hierarchy;


      var serviceType = (0, _get2.default)(config, ['recordTypes', recordType, 'serviceConfig', 'serviceType']);

      var HierarchyEditor = serviceType === 'object' ? _TypedHierarchyEditor2.default : _UntypedHierarchyEditor2.default;

      return _react2.default.createElement(HierarchyEditor, {
        csid: csid,
        messages: messages,
        parentTypeOptionListName: parentTypeOptionListName,
        childTypeOptionListName: childTypeOptionListName,
        recordType: recordType,
        vocabulary: vocabulary,
        value: hierarchy,
        readOnly: readOnly,
        showParent: showParent,
        showChildren: showChildren,
        onCommit: this.handleCommit,
        onAddChild: this.handleAddChild,
        onRemoveChild: this.handleRemoveChild
      });
    }
  }, {
    key: 'renderReparentNotifier',
    value: function renderReparentNotifier() {
      var csid = this.props.csid;
      var hierarchy = this.state.hierarchy;
      var config = this.context.config;


      var newChildRefNames = hierarchy.get('children').filter(function (child) {
        return !child.get('relCsid');
      }).map(function (child) {
        return child.get('refName');
      });

      return _react2.default.createElement(_HierarchyReparentNotifierContainer2.default, {
        config: config,
        csid: csid,
        childRefNames: newChildRefNames
      });
    }
  }, {
    key: 'renderSiblings',
    value: function renderSiblings() {
      var _props4 = this.props,
          csid = _props4.csid,
          messages = _props4.messages,
          showSiblings = _props4.showSiblings;


      if (!showSiblings) {
        return undefined;
      }

      var _context2 = this.context,
          config = _context2.config,
          recordType = _context2.recordType;
      var hierarchy = this.state.hierarchy;


      return _react2.default.createElement(_HierarchySiblingListContainer2.default, {
        config: config,
        csid: csid,
        parentCsid: hierarchy.getIn(['parent', 'csid']),
        recordType: recordType,
        title: _react2.default.createElement(_reactIntl.FormattedMessage, messages.siblings)
      });
    }
  }, {
    key: 'render',
    value: function render() {
      return _react2.default.createElement(
        _cspaceLayout.Row,
        null,
        this.renderHierarchy(),
        this.renderSiblings(),
        this.renderReparentNotifier()
      );
    }
  }]);

  return HierarchyInput;
}(_react.Component);

exports.default = HierarchyInput;


HierarchyInput.propTypes = propTypes;
HierarchyInput.defaultProps = defaultProps;
HierarchyInput.contextTypes = contextTypes;