"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

exports.__esModule = true;
exports.keyboardSortableListItem = keyboardSortableListItem;
exports.keyboardSortableListItemDefaultProps = exports.keyboardSortableDesc = void 0;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));

var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _playMessage = require("../core/utils/playMessage");

var _constants = require("../utils/constants");

var _react = _interopRequireDefault(require("react"));

var Component = _react.default.Component;
var keyboardSortableDesc = {
  onFocusDesc: 'TRANSLATE:ON_FOCUS_DESC',
  onGrabDescA: 'TRANSLATE:ON_GRAB_DESC_A',
  onGrabDescB: 'TRANSLATE:ON_GRAB_DESC_B',
  onDragDesc: 'TRANSLATE:ON_DRAG_DESC',
  onDropDesc: 'TRANSLATE:ON_DROP_DESC',
  onCancelDesc: 'TRANSLATE:ON_CANCEL_DESC'
};
exports.keyboardSortableDesc = keyboardSortableDesc;
var keyboardSortableListItemDefaultProps = {
  onMove: null,
  onHover: null,
  dragItemName: 'TRANSLATE:DRAGGABLE_ITEM'
};
exports.keyboardSortableListItemDefaultProps = keyboardSortableListItemDefaultProps;

function keyboardSortableListItem(DecoratedComponent) {
  var _class, _temp;

  return _temp = _class =
  /*#__PURE__*/
  function (_Component) {
    (0, _inheritsLoose2.default)(KeyboardSortableListItem, _Component);

    function KeyboardSortableListItem(props, context) {
      var _this;

      _this = _Component.call(this, props, context) || this;
      (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onHandlerKeyUp", function (event) {
        if (_this.state.isExistingFromReorderingMode) {
          event.stopPropagation();
        }
      });
      _this.state = {
        originalIndexBeforeOrdering: -1,
        isReorderingMode: false,
        isExistingFromReorderingMode: false
      };
      _this.reorderActionHandler = _this.reorderActionHandler.bind((0, _assertThisInitialized2.default)(_this));
      _this.dragHandler = null;
      _this.prevDragHandler = null;
      return _this;
    }

    var _proto = KeyboardSortableListItem.prototype;

    _proto.componentDidMount = function componentDidMount() {
      if (this.dragHandler) {
        this.register();
      }

      document.addEventListener('click', this.handleOutsideClick.bind(this));
    };

    _proto.componentDidUpdate = function componentDidUpdate() {
      if (this.dragHandler) {
        this.register();

        if (this.state.isReorderingMode) {
          this.dragHandler.focus();
        }
      } else if (!this.dragHandler && !this.prevDragHandler) {
        this.unregister();
      }
    };

    _proto.componentWillUnmount = function componentWillUnmount() {
      if (this.dragHandler) {
        this.unregister();
      }

      document.removeEventListener('click', this.handleOutsideClick.bind(this));
    };

    _proto.register = function register() {
      var _this$props = this.props,
          index = _this$props.index,
          dndId = _this$props.dndId;
      this.context.register(index, dndId);
      var currentKeyDownListener = this.dragHandler._keydownListener;

      if (currentKeyDownListener) {
        this.dragHandler.removeEventListener('keydown', currentKeyDownListener);
        this.dragHandler.removeEventListener('keyup', this.onHandlerKeyUp);
      }

      this.dragHandler.addEventListener('keydown', this.reorderActionHandler);
      this.dragHandler.addEventListener('keyup', this.onHandlerKeyUp);
      this.dragHandler._keydownListener = this.reorderActionHandler;
      this.dragHandler.setAttribute('role', 'option');
      this.dragHandler.setAttribute('aria-label', this.props.dragItemName + ", " + KeyboardSortableListItem.keyboardSortableDesc.onFocusDesc);
    };

    _proto.unregister = function unregister() {
      var _this$props2 = this.props,
          index = _this$props2.index,
          dndId = _this$props2.dndId;
      this.context.unregister(index, dndId);

      if (this.prevDragHandler) {
        this.prevDragHandler.removeEventListener('keydown', this.reorderActionHandler);
        this.prevDragHandler._keydownListener = null;
        this.prevDragHandler.removeAttribute('aria-label');
      }
    };

    _proto.createDragHandlerRef = function createDragHandlerRef(node) {
      this.prevDragHandler = this.dragHandler;
      this.dragHandler = node;
    };

    _proto.cancelReorder = function cancelReorder() {
      var originalIndexBeforeOrdering = this.state.originalIndexBeforeOrdering;
      var _this$props3 = this.props,
          index = _this$props3.index,
          onMove = _this$props3.onMove,
          onHover = _this$props3.onHover,
          dndId = _this$props3.dndId;
      var isMovedDown = index > originalIndexBeforeOrdering;

      if (isMovedDown) {
        var getPrevDropTarget = this.context.getPrevDropTarget;

        while (index > originalIndexBeforeOrdering) {
          var dropDndId = getPrevDropTarget(index).dndId;

          if (dropDndId) {
            reorder(dropDndId, index, isMovedDown);
          }

          index--;
        }
      } else {
        var getNextDropTarget = this.context.getNextDropTarget;

        while (index < originalIndexBeforeOrdering) {
          var _dropDndId = getNextDropTarget(index).dndId;

          if (_dropDndId) {
            reorder(_dropDndId, index, isMovedDown);
          }

          index++;
        }
      }

      this.announceCancelReorderItem();

      function reorder(dropDndId, index, isMovingDown) {
        if (onMove) {
          onMove(dropDndId, dndId);
        } else {
          (function (index) {
            setTimeout(function (_) {
              onHover({
                index: index
              }, {
                index: index + (isMovingDown ? -1 : 1)
              }, true);
            });
          })(index);
        }
      }
    };

    _proto.reorderActionHandler = function reorderActionHandler(e) {
      var index = this.props.index;
      var _this$state = this.state,
          originalIndexBeforeOrdering = _this$state.originalIndexBeforeOrdering,
          isReorderingMode = _this$state.isReorderingMode;

      switch (e.keyCode) {
        case _constants.KeyCodes.TAB:
        case _constants.KeyCodes.ESC:
          if (isReorderingMode) {
            e.stopPropagation();
            this.exitReorderingMode();
          }

          break;

        case _constants.KeyCodes.SPACE:
        case _constants.KeyCodes.ENTER:
          e.preventDefault();

          if (isReorderingMode) {
            this.announceDropItem();
          } else {
            this.announceGrabItem();
          }

          this.setState({
            originalIndexBeforeOrdering: originalIndexBeforeOrdering < 0 ? index : -1,
            isReorderingMode: !isReorderingMode,
            isExistingFromReorderingMode: isReorderingMode
          });
          break;

        case _constants.KeyCodes.ARROW_LEFT:
        case _constants.KeyCodes.ARROW_UP:
          if (isReorderingMode) {
            e.preventDefault();

            var _this$context$getPrev = this.context.getPrevDropTarget(index),
                dndId = _this$context$getPrev.dndId,
                targetIndex = _this$context$getPrev.index;

            if (dndId || dndId === 0) {
              this.announceMovingItem(targetIndex);
              this.reorder(dndId, false);
            }
          }

          break;

        case _constants.KeyCodes.ARROW_RIGHT:
        case _constants.KeyCodes.ARROW_DOWN:
          if (isReorderingMode) {
            e.preventDefault();

            var _this$context$getNext = this.context.getNextDropTarget(index),
                _dndId = _this$context$getNext.dndId,
                _targetIndex = _this$context$getNext.index;

            if (_dndId || _dndId === 0) {
              this.announceMovingItem(_targetIndex);
              this.reorder(_dndId, true);
            }
          }

      }
    }
    /**
     * @param targetId moving destination. drop target's id
     * @param movingDown moving direction. direction moving up or moving down
     */
    ;

    _proto.reorder = function reorder(targetId, movingDown) {
      var _this$props4 = this.props,
          index = _this$props4.index,
          dndId = _this$props4.dndId,
          onMove = _this$props4.onMove,
          onHover = _this$props4.onHover;

      if (onMove) {
        onMove(dndId, targetId);
      } else {
        onHover({
          index: index
        }, {
          index: index + (movingDown ? 1 : -1)
        }, true);
      }
    };

    _proto.exitReorderingMode = function exitReorderingMode() {
      var index = this.props.index;

      if (this.state.isReorderingMode && index !== this.state.originalIndexBeforeOrdering) {
        this.cancelReorder();
      }

      this.setState({
        isReorderingMode: false,
        originalIndexBeforeOrdering: -1,
        isExistingFromReorderingMode: this.state.isReorderingMode
      });
    };

    _proto.handleOutsideClick = function handleOutsideClick() {
      if (document.activeElement !== this.dragHandler && this.state.isReorderingMode) {
        this.exitReorderingMode();
      }
    };

    _proto.announceGrabItem = function announceGrabItem() {
      var index = this.props.index;
      var dragItemName = this.props.dragItemName;
      var _KeyboardSortableList = KeyboardSortableListItem.keyboardSortableDesc,
          onGrabDescA = _KeyboardSortableList.onGrabDescA,
          onGrabDescB = _KeyboardSortableList.onGrabDescB;
      (0, _playMessage.playMessage)(dragItemName + ", " + onGrabDescA + ": " + (index + 1) + ". " + onGrabDescB);
    };

    _proto.announceMovingItem = function announceMovingItem(currentIndex) {
      var dragItemName = this.props.dragItemName;
      var onDragDesc = KeyboardSortableListItem.keyboardSortableDesc.onDragDesc;
      (0, _playMessage.playMessage)(dragItemName + ", " + onDragDesc + ": " + (currentIndex + 1));
    };

    _proto.announceDropItem = function announceDropItem() {
      var index = this.props.index;
      var dragItemName = this.props.dragItemName;
      var onDropDesc = KeyboardSortableListItem.keyboardSortableDesc.onDropDesc;
      (0, _playMessage.playMessage)(dragItemName + ", " + onDropDesc + ": " + (index + 1));
    };

    _proto.announceCancelReorderItem = function announceCancelReorderItem() {
      var dragItemName = this.props.dragItemName;
      var onCancelDesc = KeyboardSortableListItem.keyboardSortableDesc.onCancelDesc;
      (0, _playMessage.playMessage)(dragItemName + ", " + onCancelDesc);
    };

    _proto.render = function render() {
      return _react.default.createElement(DecoratedComponent, (0, _extends2.default)({
        isKeyboardDragging: this.state.isReorderingMode,
        connectDragHandler: this.createDragHandlerRef.bind(this)
      }, this.props));
    };

    return KeyboardSortableListItem;
  }(Component), (0, _defineProperty2.default)(_class, "keyboardSortableDesc", keyboardSortableDesc), (0, _defineProperty2.default)(_class, "contextTypes", {
    register: _propTypes.default.func.isRequired,
    unregister: _propTypes.default.func.isRequired,
    getPrevDropTarget: _propTypes.default.func.isRequired,
    getNextDropTarget: _propTypes.default.func.isRequired
  }), (0, _defineProperty2.default)(_class, "propTypes", {
    index: _propTypes.default.number.isRequired,
    dndId: _propTypes.default.any.isRequired,
    onMove: checkReorderCallbackProp,
    onHover: checkReorderCallbackProp,
    dragItemName: _propTypes.default.string.isRequired
  }), (0, _defineProperty2.default)(_class, "defaultProps", keyboardSortableListItemDefaultProps), _temp;
}

function checkReorderCallbackProp(props, propName, componentName) {
  if (!props.onMove && !props.onHover) {
    return new Error("One of props 'onHide' or 'onHover' need to be specified in " + componentName);
  }

  if (props[propName]) {
    for (var _len = arguments.length, rest = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
      rest[_key - 3] = arguments[_key];
    }

    return _propTypes.default.func.apply(_propTypes.default, [props, propName, componentName].concat(rest));
  }

  return null;
}