import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _createClass from 'babel-runtime/helpers/createClass';
/**
 * @文件说明: Handlers.ZoomInOut 地图鼠标拉框放大/缩小交互
 * @创建人: pjtools@vip.qq.com
 * @创建时间: 2020-05-20 09:15:42
 */

import assign from 'lodash/assign';
import DOM from '../util/dom';

// 地地图鼠标拉框放大/缩小交互的默认选项参数
var defaultZoomInOutOptions = {
  // 地图缩放模式，可选项：[ in<放大> | out<缩小> ]
  mode: 'in'
};

var ZoomInOut = function () {
  function ZoomInOut(iMapApi) {
    _classCallCheck(this, ZoomInOut);

    this.iMapApi = iMapApi;
    this.map = this.iMapApi && this.iMapApi.map;
    var mapboxgl = this.iMapApi.exports.mapboxgl;

    this.mapboxgl = mapboxgl;
    // 地图容器对象
    this._container = this.iMapApi.getMapContainer();
    // 地图Canvas容器对象
    this._el = this.iMapApi.getMapCanvasConatainer();
    // 记录交互绑定事件对象
    this._events = {};
    // 鼠标事件执行的对比范围
    this._clickTolerance = 1;
    // 交互的禁用/启用状态
    this._enabled = false;
    // 交互的活动状态
    this._active = false;
  }

  /**
   * 激活地图鼠标拉框放大/缩小交互功能
   * @param {Object} options 交互选项
   */


  _createClass(ZoomInOut, [{
    key: 'enable',
    value: function enable() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

      !this._cursor && (this._cursor = this.iMapApi.Handlers.cursor);
      // 清除历史交互模式的参数选项
      if (this.isEnabled()) {
        this.reset();
        this._removeEvents();
      }
      // 合并选项参数
      this._options = assign({}, defaultZoomInOutOptions, options);
      this._options.mode = ['in', 'out'].indexOf(this._options.mode.toLowerCase()) !== -1 ? this._options.mode.toLowerCase() : 'in';
      // 设置激活模式地图光标
      this._cursor.enable({
        cursor: 'default',
        tip: {
          icon: 'zoom-' + this._options.mode,
          content: '\u62C9\u6846' + (this._options.mode === 'out' ? '缩小' : '放大') + '\uFF0CEsc\u952E\u53D6\u6D88'
        }
      }, this);
      // 绑定交互事件
      this._events.mousedown = DOM.onEventListener(this._el, 'mousedown', this._handleMapMouseDown.bind(this));
      this._events.keydown = DOM.onEventListener(window.document, 'keydown', this._handleWindowKeyDown.bind(this));
      // 更新状态
      this._enabled = true;
    }

    /**
     * 禁用地图鼠标拉框放大/缩小交互功能
     */

  }, {
    key: 'disable',
    value: function disable() {
      if (!this.isEnabled()) {
        return;
      }
      // 清除活动状态过程中对象及交互事件
      this.reset();
      this._removeEvents();
      // 清除交互模式的参数选项
      this._options = defaultZoomInOutOptions;
      // 更新状态
      this._enabled = false;
      // 移除光标模式
      this._cursor && this._cursor.disable(false);
    }

    /**
     * 获取当前交互的禁用/启用状态
     */

  }, {
    key: 'isEnabled',
    value: function isEnabled() {
      return !!this._enabled;
    }

    /**
     * 获取当前交互的活动状态
     */

  }, {
    key: 'isActive',
    value: function isActive() {
      return !!this._active;
    }

    /**
     * 重置地图鼠标拉框放大/缩小交互到初始激活阶段
     */

  }, {
    key: 'reset',
    value: function reset() {
      // 移除拉框DOM对象
      if (this._box) {
        DOM.remove(this._box);
        this._box = null;
        delete this._box;
      }
      // 激活地图拖拽
      DOM.enableDrag();
      this.map.dragPan && this.map.dragPan.enable();
      // 删除坐标记录对象
      this._startPos && delete this._startPos;
      this._lastPos && delete this._lastPos;
      // 解绑事件
      if (this._events.mousemove) {
        this._events.mousemove.remove();
        delete this._events.mousemove;
      }
      if (this._events.mouseup) {
        this._events.mouseup.remove();
        delete this._events.mouseup;
      }
      // 更新状态
      this._active = false;
    }

    // 执行地图的MouseDown事件

  }, {
    key: '_handleMapMouseDown',
    value: function _handleMapMouseDown(e) {
      // 判断鼠标按钮及禁启用状态
      if (!this.isEnabled() || DOM.mouseButton(e) !== 0) {
        return;
      }
      // 禁用地图拖拽
      DOM.disableDrag(this.map);
      this.map.dragPan && this.map.dragPan.disable();
      // 记录当前鼠标坐标
      var point = DOM.mousePos(this._el, e, this.mapboxgl);
      this._startPos = this._lastPos = point;
      // 绑定事件
      this._events.mousemove = DOM.onEventListener(window.document, 'mousemove', this._handleWindowMouseMove.bind(this));
      this._events.mouseup = DOM.onEventListener(window.document, 'mouseup', this._handleWindowMouseUp.bind(this));
      // 更新状态
      this._active = true;
    }

    // 执行Window的MouseMove事件

  }, {
    key: '_handleWindowMouseMove',
    value: function _handleWindowMouseMove(e) {
      if (!this.isActive()) {
        return;
      }
      var point = DOM.mousePos(this._el, e, this.mapboxgl);
      // 判断鼠标移动距离，限制Move事件节流
      if (this._lastPos.equals(point) || !this._box && point.dist(this._startPos) < this._clickTolerance) {
        return;
      }
      var p0 = this._startPos;
      this._lastPos = point;
      // 创建拉框的DOM元素
      if (!this._box) {
        this._box = DOM.create('div', 'mapboxgl-boxzoom', this._container);
        this.iMapApi.Evented.fire('zoominout.start', { e: e, startPos: point });
      }
      // 计算绘制的Box宽度、偏移属性样式
      var minX = Math.min(p0.x, point.x);
      var maxX = Math.max(p0.x, point.x);
      var minY = Math.min(p0.y, point.y);
      var maxY = Math.max(p0.y, point.y);
      DOM.setTransform(this._box, 'translate(' + minX + 'px,' + minY + 'px)');
      this._box.style.width = maxX - minX + 'px';
      this._box.style.height = maxY - minY + 'px';
    }

    // 执行Window的MouseUp事件

  }, {
    key: '_handleWindowMouseUp',
    value: function _handleWindowMouseUp(e) {
      var _this = this;

      if (!this.isActive() || DOM.mouseButton(e) !== 0) {
        return;
      }
      var p0 = this._startPos;
      var p1 = DOM.mousePos(this._el, e, this.mapboxgl);
      // 清除鼠标拉框交互时的临时对象
      this.reset();
      DOM.suppressClick();
      // 执行地图的回调事件及缩放
      if (p0.x === p1.x && p0.y === p1.y) {
        this.iMapApi.Evented.fire('zoominout.cancel', { e: e });
      } else {
        // 根据模式执行缩放计算范围坐标
        var point0 = p0;
        var point1 = p1;
        if (this._options.mode === 'out') {
          // 计算缩放比例
          var pixWidth = Math.abs(p1.x - p0.x);
          var pixHeight = Math.abs(p1.y - p0.y);
          var mapRect = this._container.getBoundingClientRect();
          var zoomFactor = Math.min(mapRect.height / pixHeight, mapRect.width / pixWidth);
          // 获取拉框矩形的中心点
          var mapboxgl = this.mapboxgl;
          var center = new mapboxgl.Point((p0.x + p1.x) / 2, (p0.y + p1.y) / 2);
          var xmin = center.x - mapRect.width / 2 * zoomFactor;
          var xmax = center.x + mapRect.width / 2 * zoomFactor;
          var ymin = center.y - mapRect.height / 2 * zoomFactor;
          var ymax = center.y + mapRect.height / 2 * zoomFactor;
          point0 = new mapboxgl.Point(xmin, ymin);
          point1 = new mapboxgl.Point(xmax, ymax);
        }
        // 对地图执行范围缩放动画
        this.map.fitScreenCoordinates(point0, point1, this.iMapApi.getRotate(), { linear: true });
        this.map.once('moveend', function () {
          _this.iMapApi.Evented.fire('zoominout.end', { e: e, startPos: point0, endPos: point1 });
        });
      }
    }

    // 执行键盘Keydown事件

  }, {
    key: '_handleWindowKeyDown',
    value: function _handleWindowKeyDown(e) {
      // 判断是否按下ESC取消操作
      if (e && e.keyCode && e.keyCode === 27) {
        this.disable();
        this.iMapApi.Evented.fire('zoominout.cancel', { e: e });
      }
    }

    // 解绑当前交互的事件绑定

  }, {
    key: '_removeEvents',
    value: function _removeEvents() {
      var events = this._events || {};
      var keys = Object.keys(events);
      for (var i = keys.length - 1; i >= 0; i--) {
        var key = keys[i];
        if (events[key]) {
          events[key].remove();
          delete events[key];
        }
      }
    }
  }]);

  return ZoomInOut;
}();

export default ZoomInOut;