function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

/**
 * @class qrenderer.graphic.drag.DragDropMgr
 * Global drag-drop manager, hold Ctrl for multi-selection.
 * 
 * 
 * 全局拖拽管理器,支持同时拖拽多个元素,按住 Ctrl 键可以多选。
 * 
 * @author 大漠穷秋 <damoqiongqiu@126.com>
 * @docauthor 大漠穷秋 <damoqiongqiu@126.com>
 */
var DragDropMgr =
/*#__PURE__*/
function () {
  /**
   * @method constructor DragDropMgr
   * @param {GlobalEventDispatcher} dispatcher 
   */
  function DragDropMgr(dispatcher) {
    _classCallCheck(this, DragDropMgr);

    this.dispatcher = dispatcher;
    this.selectionMap = new Map();
  }

  _createClass(DragDropMgr, [{
    key: "startListen",
    value: function startListen() {
      this.dispatcher.on('mousedown', this.dragStart, this);
      return this;
    }
  }, {
    key: "stopListen",
    value: function stopListen() {
      this.clearSelectionMap();
      this._draggingItem = null;
      this._dropTarget = null;
      this._x = 0;
      this._y = 0;
      this.dispatcher.off('mousedown', this.dragStart, this);
      this.dispatcher.off('pagemousemove', this.dragging, this);
      this.dispatcher.off('pagemouseup', this.dragEnd, this);
      return this;
    }
    /**
     * @private
     * @method dragStart
     * Start dragging.
     * 
     * 
     * 开始拖动。
     * @param {Event} e 
     */

  }, {
    key: "dragStart",
    value: function dragStart(e) {
      var _this = this;

      var el = e.target;
      var event = e.event;
      this._draggingItem = el;

      if (!el) {
        this.clearSelectionMap();
        return;
      }

      if (!el.draggable) {
        return;
      }

      if (!event.ctrlKey && !this.selectionMap.get(el.id)) {
        this.clearSelectionMap();
      }

      el.dragging = true;
      this.selectionMap.set(el.id, el);
      this._x = e.offsetX;
      this._y = e.offsetY;
      this.dispatcher.on('pagemousemove', this.dragging, this);
      this.dispatcher.on('pagemouseup', this.dragEnd, this);
      this.selectionMap.forEach(function (el) {
        _this.dispatcher.dispatchToElement(_this.normalizeParam(el, e), 'dragstart', e.event);
      });
    }
    /**
     * @private
     * @method dragging
     * Dragging.
     * 
     * 
     * 拖动过程中。
     * @param {Event} e 
     */

  }, {
    key: "dragging",
    value: function dragging(e) {
      var _this2 = this;

      var x = e.offsetX;
      var y = e.offsetY;
      var dx = x - this._x;
      var dy = y - this._y;
      this._x = x;
      this._y = y;
      this.selectionMap.forEach(function (el) {
        if (el.beforeMove(dx, dy, e, el)) {
          el.move(dx, dy, e);
          el.afterMove(dx, dy, e, el);
        }

        _this2.dispatcher.dispatchToElement(_this2.normalizeParam(el, e), 'drag', e.event);
      });
      var dropTarget = this.dispatcher.findHover(x, y, this._draggingItem).target;
      var lastDropTarget = this._dropTarget;
      this._dropTarget = dropTarget;

      if (this._draggingItem !== dropTarget) {
        if (lastDropTarget && dropTarget !== lastDropTarget) {
          this.dispatcher.dispatchToElement(this.normalizeParam(lastDropTarget, e), 'dragleave', e.event);
        }

        if (dropTarget && dropTarget !== lastDropTarget) {
          this.dispatcher.dispatchToElement(this.normalizeParam(dropTarget, e), 'dragenter', e.event);
        }
      }
    }
    /**
     * @private
     * @method dragEnd
     * Drag end.
     * 
     * 
     * 拖动结束。
     * @param {Event} e 
     */

  }, {
    key: "dragEnd",
    value: function dragEnd(e) {
      var _this3 = this;

      this.selectionMap.forEach(function (el) {
        el.dragging = false;

        _this3.dispatcher.dispatchToElement(_this3.normalizeParam(el, e), 'dragend', e.event);
      });
      this.dispatcher.off('pagemousemove', this.dragging, this);
      this.dispatcher.off('pagemouseup', this.dragEnd, this);

      if (this._dropTarget) {
        this.dispatcher.dispatchToElement(this.normalizeParam(this._dropTarget, e), 'drop', e.event);
      }

      this._dropTarget = null;
    }
    /**
     * @private
     * @method normalizeParam
     * @param {Element} target 
     * @param {Event} e 
     */

  }, {
    key: "normalizeParam",
    value: function normalizeParam(target, e) {
      return {
        target: target,
        topTarget: e && e.topTarget
      };
    }
    /**
     * @method getSelectedItems
     * Get all selected items.
     * 
     * 
     * 获取当前选中的所有元素。
     * @return {Map} selectionMap
     */

  }, {
    key: "getSelectedItems",
    value: function getSelectedItems() {
      return this.selectionMap;
    }
    /**
     * @method clearSelectionMap
     * Clear all selected items.
     * 
     * 
     * 清除选中。
     */

  }, {
    key: "clearSelectionMap",
    value: function clearSelectionMap() {
      this.selectionMap.forEach(function (el) {
        el.dragging = false;
      });
      this.selectionMap.clear();
    }
  }]);

  return DragDropMgr;
}();

module.exports = DragDropMgr;