'use strict';

exports.__esModule = true;

var _extends3 = require('babel-runtime/helpers/extends');

var _extends4 = _interopRequireDefault(_extends3);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');

var _reactDom2 = _interopRequireDefault(_reactDom);

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

var _propTypes2 = _interopRequireDefault(_propTypes);

var _DraftOffsetKey = require('draft-js/lib/DraftOffsetKey');

var _rcAnimate = require('rc-animate');

var _rcAnimate2 = _interopRequireDefault(_rcAnimate);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _domScrollIntoView = require('dom-scroll-into-view');

var _domScrollIntoView2 = _interopRequireDefault(_domScrollIntoView);

var _Nav = require('./Nav.react');

var _Nav2 = _interopRequireDefault(_Nav);

var _SuggestionWrapper = require('./SuggestionWrapper.react');

var _SuggestionWrapper2 = _interopRequireDefault(_SuggestionWrapper);

var _insertMention = require('../utils/insertMention');

var _insertMention2 = _interopRequireDefault(_insertMention);

var _clearMention = require('../utils/clearMention');

var _clearMention2 = _interopRequireDefault(_clearMention);

var _getOffset = require('../utils/getOffset');

var _getOffset2 = _interopRequireDefault(_getOffset);

var _getMentions = require('../utils/getMentions');

var _getMentions2 = _interopRequireDefault(_getMentions);

var _getSearchWord2 = require('../utils/getSearchWord');

var _getSearchWord3 = _interopRequireDefault(_getSearchWord2);

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

var isNotFalse = function isNotFalse(i) {
  return i !== false;
};

var Suggestions = function (_React$Component) {
  (0, _inherits3['default'])(Suggestions, _React$Component);

  function Suggestions() {
    (0, _classCallCheck3['default'])(this, Suggestions);

    var _this = (0, _possibleConstructorReturn3['default'])(this, _React$Component.call(this));

    _this.onEditorStateChange = function (editorState) {
      var offset = _this.props.store.getOffset();
      if (offset.size === 0) {
        _this.closeDropDown();
        return editorState;
      }
      var selection = editorState.getSelection();

      // 淇: 鐒︾偣绉诲嚭鍐嶇Щ鍏ユ椂, dropdown 浼氶棯鍔ㄤ竴涓�
      // 鍘熷洜: https://github.com/facebook/draft-js/blob/67c5e69499e3b0c149ce83b004872afdf4180463/src/component/handlers/edit/editOnFocus.js#L33
      // 姝ゅ寮哄埗 update 浜嗕竴涓�,鍥犳 onEditorStateChange 浼� call 涓ゆ
      if (!_this.props.callbacks.getEditorState().getSelection().getHasFocus() && selection.getHasFocus()) {
        return editorState;
      }

      var _getSearchWord = (0, _getSearchWord3['default'])(editorState, selection),
          word = _getSearchWord.word;

      if (!word) {
        _this.closeDropDown();
        return editorState;
      }
      var selectionInsideMention = offset.map(function (_ref) {
        var offsetKey = _ref.offsetKey;

        var _decode = (0, _DraftOffsetKey.decode)(offsetKey),
            blockKey = _decode.blockKey,
            decoratorKey = _decode.decoratorKey,
            leafKey = _decode.leafKey;

        if (blockKey !== selection.anchorKey) {
          return false;
        }
        var leaf = editorState.getBlockTree(blockKey).getIn([decoratorKey, 'leaves', leafKey]);
        if (!leaf) {
          return false;
        }
        var startKey = leaf.get('start');
        var endKey = leaf.get('end');
        // 澶勭悊鍙湁涓€涓� `@` 绗﹀彿鏃剁殑鎯呭喌
        if (!word) {
          return false;
        }
        if (startKey === endKey - 1) {
          return selection.anchorOffset >= startKey + 1 && selection.anchorOffset <= endKey ? offsetKey : false;
        }
        return selection.anchorOffset > startKey + 1 && selection.anchorOffset <= endKey ? offsetKey : false;
      });

      var selectionInText = selectionInsideMention.some(isNotFalse);
      _this.activeOffsetKey = selectionInsideMention.find(isNotFalse) || _this.activeOffsetKey;
      var trigger = _this.props.store.getTrigger(_this.activeOffsetKey);

      if (!selectionInText || !selection.getHasFocus()) {
        _this.closeDropDown();
        return editorState;
      }
      var searchValue = word.substring(trigger.length, word.length);
      if (_this.lastSearchValue !== searchValue || _this.lastTrigger !== trigger) {
        _this.lastSearchValue = searchValue;
        _this.lastTrigger = trigger;
        _this.props.onSearchChange(searchValue, trigger);
      }
      if (!_this.state.active) {
        // 鐗逛緥澶勭悊 https://github.com/ant-design/ant-design/issues/7838
        // 鏆傛椂娌℃湁鏇翠紭闆呯殑鏂规硶
        if (!trigger || word.indexOf(trigger) !== -1) {
          _this.openDropDown();
        }
      }
      return editorState;
    };

    _this.onUpArrow = function (ev) {
      ev.preventDefault();
      if (_this.props.suggestions.length > 0) {
        var newIndex = _this.state.focusedIndex - 1;
        _this.setState({
          focusedIndex: Math.max(newIndex, 0)
        });
      }
    };

    _this.onBlur = function (ev) {
      ev.preventDefault();
      _this.closeDropDown();
    };

    _this.onDownArrow = function (ev) {
      ev.preventDefault();
      var newIndex = _this.state.focusedIndex + 1;
      _this.setState({
        focusedIndex: newIndex >= _this.props.suggestions.length ? 0 : newIndex
      });
    };

    _this.getContainer = function () {
      var popupContainer = document.createElement('div');
      var mountNode = void 0;
      if (_this.props.getSuggestionContainer) {
        mountNode = _this.props.getSuggestionContainer();
        popupContainer.style.position = 'relative';
      } else {
        mountNode = document.body;
      }
      mountNode.appendChild(popupContainer);
      return popupContainer;
    };

    _this.handleKeyBinding = function (command) {
      return command === 'split-block';
    };

    _this.handleReturn = function (ev) {
      ev.preventDefault();
      var selectedSuggestion = _this.props.suggestions[_this.state.focusedIndex];
      if (selectedSuggestion) {
        if (_react2['default'].isValidElement(selectedSuggestion)) {
          _this.onMentionSelect(selectedSuggestion.props.value, selectedSuggestion.props.data);
        } else {
          _this.onMentionSelect(selectedSuggestion);
        }
        _this.lastSearchValue = null;
        _this.lastTrigger = null;
        return true;
      }
      return false;
    };

    _this.renderReady = function () {
      var container = _this.dropdownContainer;
      if (!container) {
        return;
      }
      var active = _this.state.active;
      var activeOffsetKey = _this.activeOffsetKey;

      var offset = _this.props.store.getOffset();
      var dropDownPosition = offset.get(activeOffsetKey);

      if (active && dropDownPosition) {
        var placement = _this.props.placement;
        var dropDownStyle = _this.getPositionStyle(true, dropDownPosition.position());

        // Check if the above space is crowded
        var isTopCrowded = parseFloat(dropDownStyle.top) - window.scrollY - container.offsetHeight < 0;
        // Check if the under space is crowded
        var isBottomCrowded = (window.innerHeight || document.documentElement.clientHeight) - (parseFloat(dropDownStyle.top) - window.scrollY) - container.offsetHeight < 0;

        if (placement === 'top' && !isTopCrowded) {
          // The above space isn't crowded
          dropDownStyle.top = (parseFloat(dropDownStyle.top) - container.offsetHeight || 0) + 'px';
        }

        if (placement === 'bottom' && isBottomCrowded && !isTopCrowded) {
          // The above space isn't crowded and the under space is crowded.
          dropDownStyle.top = (parseFloat(dropDownStyle.top) - container.offsetHeight || 0) + 'px';
        }

        Object.keys(dropDownStyle).forEach(function (key) {
          container.style[key] = dropDownStyle[key];
        });
      }

      if (!_this.focusItem) {
        return;
      }
      (0, _domScrollIntoView2['default'])(_reactDom2['default'].findDOMNode(_this.focusItem), container, {
        onlyScrollIfNeeded: true
      });
    };

    _this.getNavigations = function () {
      var _this$props = _this.props,
          prefixCls = _this$props.prefixCls,
          suggestions = _this$props.suggestions;
      var focusedIndex = _this.state.focusedIndex;

      return suggestions.length ? _react2['default'].Children.map(suggestions, function (element, index) {
        var focusItem = index === focusedIndex;
        var ref = focusItem ? function (node) {
          _this.focusItem = node;
        } : null;
        var mentionClass = (0, _classnames2['default'])(prefixCls + '-dropdown-item', {
          focus: focusItem
        });
        if (_react2['default'].isValidElement(element)) {
          return _react2['default'].cloneElement(element, {
            className: mentionClass,
            onMouseDown: function onMouseDown() {
              return _this.onDropdownMentionSelect(element.props.value, element.props.data);
            },
            ref: ref
          });
        }
        return _react2['default'].createElement(
          _Nav2['default'],
          {
            ref: ref,
            className: mentionClass,
            onMouseDown: function onMouseDown() {
              return _this.onDropdownMentionSelect(element);
            }
          },
          element
        );
      }, _this) : _react2['default'].createElement(
        'div',
        { className: prefixCls + '-dropdown-notfound ' + prefixCls + '-dropdown-item' },
        _this.props.notFoundContent
      );
    };

    _this.state = {
      isActive: false,
      focusedIndex: 0,
      container: false
    };
    return _this;
  }

  Suggestions.prototype.componentDidMount = function componentDidMount() {
    this.props.callbacks.onChange = this.onEditorStateChange;
  };

  Suggestions.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
    if (nextProps.suggestions.length !== this.props.suggestions.length) {
      this.setState({
        focusedIndex: 0
      });
    }
  };

  Suggestions.prototype.onDropdownMentionSelect = function onDropdownMentionSelect(mention, data) {
    var _this2 = this;

    setTimeout(function () {
      _this2.onMentionSelect(mention, data);
    }, 100);
  };

  Suggestions.prototype.onMentionSelect = function onMentionSelect(mention, data) {
    var editorState = this.props.callbacks.getEditorState();
    var _props = this.props,
        store = _props.store,
        onSelect = _props.onSelect;

    var trigger = store.getTrigger(this.activeOffsetKey);
    if (onSelect) {
      onSelect(mention, data || mention);
    }
    if (this.props.noRedup) {
      var mentions = (0, _getMentions2['default'])(editorState.getCurrentContent(), trigger);
      if (mentions.indexOf('' + trigger + mention) !== -1) {
        // eslint-disable-next-line
        console.warn('you have specified `noRedup` props but have duplicated mentions.');
        this.closeDropDown();
        this.props.callbacks.setEditorState((0, _clearMention2['default'])(editorState));
        return;
      }
    }
    this.props.callbacks.setEditorState((0, _insertMention2['default'])(editorState, '' + trigger + mention, data, this.props.mode), true);
    this.closeDropDown();
  };

  Suggestions.prototype.getPositionStyle = function getPositionStyle(isActive, position) {
    if (this.props.getSuggestionStyle) {
      return this.props.getSuggestionStyle(isActive, position);
    }
    var container = this.props.getSuggestionContainer ? this.state.container : document.body;
    var offset = (0, _getOffset2['default'])(container);
    return position ? (0, _extends4['default'])({
      position: 'absolute',
      left: position.left - offset.left + 'px',
      top: position.top - offset.top + 'px'
    }, this.props.style) : {};
  };

  Suggestions.prototype.openDropDown = function openDropDown() {
    this.props.callbacks.onUpArrow = this.onUpArrow;
    this.props.callbacks.handleReturn = this.handleReturn;
    this.props.callbacks.handleKeyBinding = this.handleKeyBinding;
    this.props.callbacks.onDownArrow = this.onDownArrow;
    this.props.callbacks.onBlur = this.onBlur;
    this.setState({
      active: true,
      container: this.state.container || this.getContainer()
    });
  };

  Suggestions.prototype.closeDropDown = function closeDropDown() {
    this.props.callbacks.onUpArrow = null;
    this.props.callbacks.handleReturn = null;
    this.props.callbacks.handleKeyBinding = null;
    this.props.callbacks.onDownArrow = null;
    this.props.callbacks.onBlur = null;
    this.setState({
      active: false
    });
  };

  Suggestions.prototype.render = function render() {
    var _extends2,
        _this3 = this;

    var _props2 = this.props,
        prefixCls = _props2.prefixCls,
        className = _props2.className,
        placement = _props2.placement;
    var _state = this.state,
        container = _state.container,
        active = _state.active;

    var cls = (0, _classnames2['default'])((0, _extends4['default'])((_extends2 = {}, _extends2[prefixCls + '-dropdown'] = true, _extends2[prefixCls + '-dropdown-placement-' + placement] = true, _extends2), className));
    var transitionName = placement === 'top' ? 'slide-down' : 'slide-up';

    var navigations = this.getNavigations();

    return container ? _react2['default'].createElement(
      _SuggestionWrapper2['default'],
      { renderReady: this.renderReady, container: container },
      _react2['default'].createElement(
        _rcAnimate2['default'],
        { transitionName: transitionName },
        active ? _react2['default'].createElement(
          'div',
          { className: cls, ref: function ref(node) {
              _this3.dropdownContainer = node;
            } },
          navigations
        ) : null
      )
    ) : null;
  };

  return Suggestions;
}(_react2['default'].Component);

exports['default'] = Suggestions;


Suggestions.propTypes = {
  callbacks: _propTypes2['default'].object,
  suggestions: _propTypes2['default'].array,
  store: _propTypes2['default'].object,
  onSearchChange: _propTypes2['default'].func,
  prefixCls: _propTypes2['default'].string,
  mode: _propTypes2['default'].string,
  style: _propTypes2['default'].object,
  onSelect: _propTypes2['default'].func,
  getSuggestionContainer: _propTypes2['default'].func,
  notFoundContent: _propTypes2['default'].any,
  getSuggestionStyle: _propTypes2['default'].func,
  className: _propTypes2['default'].string,
  noRedup: _propTypes2['default'].bool,
  placement: _propTypes2['default'].string
};
module.exports = exports['default'];