'use strict';

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

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

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


const findParent = (csid, relations) => {
  const 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;
};

const findChildren = (csid, relations) => (0, _relationListHelpers.findNarrowerRelations)(csid, relations).sort((relationA, relationB) => {
  const displayNameA = (0, _cspaceRefname.getDisplayName)(relationA.getIn(['subject', 'refName']));
  const 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(relation => _immutable2.default.Map({
  relCsid: relation.get('csid'),
  refName: relation.getIn(['subject', 'refName']),
  type: relation.get('relationshipMetaType')
}));

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

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

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

class HierarchyInput extends _react.Component {
  constructor() {
    super();

    this.handleAddChild = this.handleAddChild.bind(this);
    this.handleRemoveChild = this.handleRemoveChild.bind(this);
    this.handleCommit = this.handleCommit.bind(this);
  }

  componentWillMount() {
    var _props = this.props;
    const csid = _props.csid,
          value = _props.value;


    this.initHierarchy(csid, value);
  }

  componentWillUpdate(nextProps) {
    var _props2 = this.props;
    const csid = _props2.csid,
          value = _props2.value;
    const nextCsid = nextProps.csid,
          nextValue = nextProps.value;


    if (nextCsid !== csid || nextValue !== value) {
      this.initHierarchy(nextCsid, nextValue);
    }
  }

  getRelationItems(hierarchy) {
    const csid = this.props.csid;


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

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

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

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

  initHierarchy(csid, value) {
    const relations = (0, _relationListHelpers.normalizeRelationList)(value);

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

    this.setState({
      hierarchy
    });
  }

  handleAddChild() {
    const onCommit = this.props.onCommit;


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


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

      if (children.size === 0) {
        // The UI renders a single blank input event if there are no children, so adding a child
        // should result in two children, not one.

        children = children.push(_immutable2.default.Map());
      }

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

      onCommit(getPath(this.props), this.getRelationItems(updatedHierarchy));
    }
  }

  handleRemoveChild(position) {
    const onCommit = this.props.onCommit;


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


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

      onCommit(getPath(this.props), this.getRelationItems(updatedHierarchy));
    }
  }

  handleCommit(path, value) {
    const onCommit = this.props.onCommit;


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


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

      onCommit(getPath(this.props), this.getRelationItems(updatedHierarchy));
    }
  }

  renderHierarchy() {
    var _props3 = this.props;
    const 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;
    const config = _context.config,
          recordType = _context.recordType,
          vocabulary = _context.vocabulary;
    const hierarchy = this.state.hierarchy;


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

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

  renderReparentNotifier() {
    const csid = this.props.csid;
    const hierarchy = this.state.hierarchy;
    const config = this.context.config;


    const newChildRefNames = hierarchy.get('children').filter(child => !child.get('relCsid')).map(child => child.get('refName'));

    return _react2.default.createElement(_HierarchyReparentNotifierContainer2.default, {
      config: config,
      csid: csid,
      childRefNames: newChildRefNames
    });
  }

  renderSiblings() {
    var _props4 = this.props;
    const csid = _props4.csid,
          messages = _props4.messages,
          showSiblings = _props4.showSiblings;


    if (!showSiblings) {
      return undefined;
    }

    var _context2 = this.context;
    const config = _context2.config,
          recordType = _context2.recordType;
    const 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)
    });
  }

  render() {
    return _react2.default.createElement(
      _cspaceLayout.Row,
      null,
      this.renderHierarchy(),
      this.renderSiblings(),
      this.renderReparentNotifier()
    );
  }
}

exports.default = HierarchyInput;
HierarchyInput.propTypes = propTypes;
HierarchyInput.defaultProps = defaultProps;
HierarchyInput.contextTypes = contextTypes;