'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 _UntypedHierarchyEditor = require('./UntypedHierarchyEditor');

var _UntypedHierarchyEditor2 = _interopRequireDefault(_UntypedHierarchyEditor);

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

var _TypedHierarchyEditor2 = _interopRequireDefault(_TypedHierarchyEditor);

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 normalizeValue = function normalizeValue(value) {
  if (!value) {
    return null;
  }

  if (_immutable2.default.List.isList(value)) {
    return value;
  }

  if (_immutable2.default.Map.isMap(value)) {
    return _immutable2.default.List.of(value);
  }

  return null;
};

var propTypes = {
  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 */
  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 contextTypes = {
  config: _propTypes2.default.object,
  csid: _propTypes2.default.string,
  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);

    _this.state = {};
    return _this;
  }

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


      this.initHierarchy(value);
    }
  }, {
    key: 'componentWillReceiveProps',
    value: function componentWillReceiveProps(nextProps) {
      var value = this.props.value;
      var nextValue = nextProps.value;


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


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

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

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

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

      return childRelationItems.push(parentRelationItem);
    }
  }, {
    key: 'initHierarchy',
    value: function initHierarchy(value) {
      var relations = normalizeValue(value);
      var parent = this.findParent(relations) || _immutable2.default.Map();
      var children = this.findChildren(relations);

      var hierarchy = _immutable2.default.fromJS({
        parent: parent,
        children: children
      });

      this.setState({
        hierarchy: hierarchy
      });
    }
  }, {
    key: 'findBroaderRelation',
    value: function findBroaderRelation(relations) {
      if (!relations) {
        return null;
      }

      var csid = this.context.csid;


      return relations.find(function (relation) {
        return relation.get('predicate') === 'hasBroader' && relation.getIn(['subject', 'csid']) === csid;
      });
    }
  }, {
    key: 'findNarrowerRelations',
    value: function findNarrowerRelations(relations) {
      var csid = this.context.csid;


      if (!relations) {
        return _immutable2.default.List();
      }

      return relations.filter(function (relation) {
        return relation.get('predicate') === '' || relation.get('predicate') === 'hasBroader' && relation.getIn(['object', 'csid']) === csid;
      });
    }
  }, {
    key: 'findChildren',
    value: function findChildren(relations) {
      return this.findNarrowerRelations(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({
          refName: relation.getIn(['subject', 'refName']),
          type: relation.get('relationshipMetaType')
        });
      });
    }
  }, {
    key: 'findParent',
    value: function findParent(relations) {
      var broaderRelation = this.findBroaderRelation(relations);

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

      return null;
    }
  }, {
    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: 'render',
    value: function render() {
      var _props = this.props,
          messages = _props.messages,
          parentTypeOptionListName = _props.parentTypeOptionListName,
          childTypeOptionListName = _props.childTypeOptionListName,
          readOnly = _props.readOnly;
      var _context = this.context,
          config = _context.config,
          csid = _context.csid,
          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(
        _cspaceLayout.Row,
        null,
        _react2.default.createElement(HierarchyEditor, {
          csid: csid,
          messages: messages,
          parentTypeOptionListName: parentTypeOptionListName,
          childTypeOptionListName: childTypeOptionListName,
          recordType: recordType,
          vocabulary: vocabulary,
          value: hierarchy,
          readOnly: readOnly,
          onCommit: this.handleCommit,
          onAddChild: this.handleAddChild,
          onRemoveChild: this.handleRemoveChild
        }),
        _react2.default.createElement(_HierarchySiblingListContainer2.default, {
          config: config,
          csid: csid,
          parentCsid: hierarchy.getIn(['parent', 'csid']),
          recordType: recordType,
          title: _react2.default.createElement(_reactIntl.FormattedMessage, messages.siblings)
        })
      );
    }
  }]);

  return HierarchyInput;
}(_react.Component);

exports.default = HierarchyInput;


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