import * as turf from "@turf/turf";
import DataUtils from '../utils/DataUtils';
import GeoJsonProvider from '../geog/GeoJsonProvider';
import LayerProvider from '../geog/LayerProvider';

/**
 * 圆形绘制类
 * @alias CircleDrawing
 *
 * @summary <用于动态绘制圆形>
 */
export default class CircleDrawing {
  /**
   * 构造函数
   * @param {Object} options -图层选项
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;

    /**
     * 最小缩放层级
     * @type {Number}
     */
    this._minzoom = DataUtils.default(options.minzoom, 10);

    // 数据源ID
    this._sourceId = 'drawing_circle';
    // 图层ID
    this._layerId = this._sourceId;
    this._lineLayerId = this._layerId + '-outline';

    this._clickEvent = null;     // 单击事件
    this._mouseMoveEvent = null; // 鼠标移动事件

    this._isDrawing = false;

    // 圆形GeoJSON对象
    this._fc = GeoJsonProvider.getEmptyFC();
  }

  /** 公有方法 **/
  /**
   * 开始绘制
   * @param {function} callback -回调函数
   */
  draw(callback) {
    // 加载图层
    if (!this._hasLayer()) {
      this._loadLayer();
    }

    const map = this._map;
    // 改变光标
    map.getCanvas().style.cursor = 'crosshair';

    this._isDrawing = true;

    let center = [], moveLonLat = [], endLonLat = [];
    let isMouseMoving = false;
    let clickNum = 0;

    let that = this;
    /**
     * 单击事件
     */
    this._clickEvent = function onClickEvent(e) {
      let lonLat = [e.lngLat.lng, e.lngLat.lat];
      if (clickNum < 1) {
        center = lonLat;
        isMouseMoving = true;
      } else {
        endLonLat = lonLat;
        isMouseMoving = false;
        clickNum = 0;

        // 设置圆形
        setCircle(center, endLonLat, true);
      }

      clickNum += 1;
    }

    /**
     * 鼠标移动事件
     */
    this._mouseMoveEvent = function onMoveEvent(e) {
      if (!isMouseMoving) return;

      moveLonLat = [e.lngLat.lng, e.lngLat.lat];
      // 设置圆形
      setCircle(center, moveLonLat);
    }

    /**
     * 设置圆形
     * @param {Array} center -中心点
     * @param {Array} end -结束点
     * @param {Boolean} isEnd -是否结束
     */
    function setCircle(center, end, isEnd = false) {
      let from = turf.point(center);
      let to = turf.point(end);
      // 计算两点间距离(千米)
      let radius = turf.distance(from, to, {
        units: 'kilometers'
      });

      // 创建缓冲区
      let feature = turf.buffer(from, radius, {
        units: 'kilometers',
        steps: 32
      });
      if (!feature) return;

      that._fc.features = [ feature ];
      // 更新数据源
      LayerProvider.updateSource(map, that._sourceId, that._fc);

      // 回调
      if (isEnd && callback) {
        callback(feature);
      }
    }

    // 绑定事件
    map.on('click', this._clickEvent);
    map.on('mousemove', this._mouseMoveEvent);
  }

  /**
   * 绘制结束
   */
  finish() {
    const map = this._map;

    // 改变光标
    map.getCanvas().style.cursor = '';
    // 允许双击缩放
    //map.doubleClickZoom.enable();

    // 解除事件绑定
    map.off('click', this._clickEvent);
    map.off('mousemove', this._mouseMoveEvent);

    this._isDrawing = false;
  }

  /**
   * 获取GeoJSON要素集
   *
   * @returns {Object} GeoJSON对象
   */
  getData() {
    return this._fc;
  }

  /**
   * 清空数据
   */
  clearData() {
    this._fc.features = [];
    // 更新数据源
    LayerProvider.updateSource(this._map, this._sourceId, this._fc)
  }

  /**
   * 移除图层
   */
  removeLayer() {
    // 移除图层
    LayerProvider.removeLayer(map, this._layerId);

    // 移除数据源
    LayerProvider.removeSource(map, this._sourceId);

    // 数据设置为空
    this._fc.features = [];
  }

  /** 私有方法 **/
  /**
   * 加载图层
   */
  _loadLayer() {
    if (this._hasLayer()) return;

    // 添加数据源
    this._map.addSource(this._sourceId, {
      type: "geojson",
      data: this._fc
    });

    // 添加图层
    this._map.addLayer({
      type: "fill",
      id: this._layerId,
      source: this._sourceId,
      minzoom: this._minzoom,
      layout: {
        visibility: "visible",
      },
      paint: {
        "fill-color": "#E6205E",
        "fill-opacity": 0.55,
        //"fill-outline-color": "#808000",
      }
    });

    // 添加边框线图层
    this._map.addLayer({
      type: "line",
      id: this._lineLayerId,
      source: this._sourceId,
      minzoom: this._minzoom,
      layout: {
        visibility: "visible",
      },
      paint: {
        "line-color": "#E6205E",
        "line-width": 2,
        "line-opacity": 0.75,
      }
    });
  }

  /**
   * 判断图层是否已加载
   *
   * @returns {Boolean}
   */
  _hasLayer() {
    return LayerProvider.hasLayer(this._map, this._layerId);
  }
}
