import DataUtils from "../utils/DataUtils";
import GeogUtils from "../utils/GeogUtils";
import FillLayer from "../layers/FillLayer";

/**
 * 动态缓冲区类
 * @alias DynamicBuffer
 * 
 * @summary <用于动态生成缓冲区>
 */
export default class DynamicBuffer {
  /**
   * 构造函数
   * @param {Object} options -图层选项 
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;
    
    /**
     * 最小缩放层级
     * @type {Number}
     */
    this._minZoom = DataUtils.default(options.minZoom, 9);

    /**
     * 颜色
     * @type {String}
     */
    this._color = DataUtils.default(options.color, '#00FFF0');
    
    /**
     * 数字提示框
     * @type {Component}
     */
    this._numberTip = DataUtils.default(options.numberTip, undefined);
    
    /**
     * 最大半径
     * @type {Number} 
     */
    this._maxRadius = DataUtils.default(options.maxRadius, 200);
    
    /**
     * 最小半径
     * @type {Number} 
     */
    this._minRadius = DataUtils.default(options.minRadius, 10);
    
    /**
     * 步长
     * @type {Number} 
     */
    this._step = DataUtils.default(options.step, 10);

    this._defaultRadius = 0.02; // 默认缓冲区半径(km)

    this._enterEvent = null, // 移入事件

    this._sourceId = 'drawing_buffer'; // 数据源ID

    // 面图层
    this._fillLayer = null;
    // 初始化图层
    this._initLayer();
  }

  /** 公有方法 **/
  /**
   * 设置缓冲区数据
   * @param {Object} data -源GeoJson要素
   * @param {Object} buffer -默认缓冲区GeoJson要素
   * @param {Number} radius -默认缓冲区半径(km)
   * @param {function} callback -回调函数
   */
  setBuffer(data, buffer, radius, callback = null) {
    const map = this._map;
    const that = this;
    
    // 设置数据
    this._fillLayer.setData(buffer);
    
    // 改变光标
    map.getCanvas().style.cursor = 'pointer';
    
    let lonLat;
    const layerId = this._fillLayer._layerId;
    this._defaultRadius = radius * 1000; // 米
    
    // 解除事件绑定
    if (this._enterEvent) {
      map.off("mouseenter", layerId, this._enterEvent);
    }
    // 隐藏数字提示框
    this.hideNumberTip();
    
    /**
     * 移入事件
     */
    this._enterEvent = (e) => {
      const feature = e.features[0];
      if (feature.properties.method === 'buffer') {
        lonLat = [e.lngLat.lng, e.lngLat.lat];

        // 显示数字提示框
        _showNumberTip(lonLat);
      }
    }

    /**
     * 显示数字提示框
     * @param {Array} lonLat -坐标
     */
    const _showNumberTip = (lonLat) => {
      that.showNumberTip(lonLat, {
        max: that._maxRadius,
        min: that._minRadius,
        num: that._defaultRadius,
        step: that._step,
      }, (n) => {
        // 刷新缓冲区
        _refreshBuffer(data, n);
      });
    }
    
    /**
     * 刷新缓冲区
     * @param {Object} data
     */
    const _refreshBuffer = (data, rr) => {
      that._defaultRadius = rr;
      const nr = rr / 1000.0;
      
      // 创建新的缓冲区
      let bufferFea = GeogUtils.buffer(data, nr);
      
      // 更新缓冲区图形
      buffer.geometry = bufferFea.geometry;
      // 更新数据
      that._fillLayer.setData(buffer);

      let newLonLat = [lonLat[0], lonLat[1]];
      // 在新坐标显示数字提示框
      _showNumberTip(newLonLat);
      
      // 回调
      if (callback) {
        callback(buffer);
      }
    }
    
    // 绑定事件
    this._fillLayer.onEvent("mouseenter", this._enterEvent);
  }  

  /**
   * 显示数字提示框
   * @param {Number[]} lonLat -经纬度
   * @param {Obhect} options -数字选项
   * @param {Function} callback -回调函数
   */
  showNumberTip(lonLat, options, callback) {
    if (!this._numberTip ||
        this._map.getCanvas().style.cursor === 'crosshair') return; 

    // 显示数字提示框
    this._numberTip.show(lonLat, {
        max: options.max || 100,
        min: options.min || 5,
        num: options.num || 20,
        step: options.step || 5
    }, callback);
  }

  /**
   * 隐藏数字提示框
   */
  hideNumberTip() {
    if (!this._numberTip) return; 
    
    this._numberTip.hide();  
  }
  
  /**
   * 移除图层 
   */
  removeLayer() {
    // 隐藏数字提示框
    this.hideNumberTip();

    // 解除事件绑定
    if (this._enterEvent) {
      this._map.off("mouseenter", this._fillLayer._layerId, this._enterEvent);
      this._enterEvent = null;
    }

    this._fillLayer.removeLayer();
  }

  /** 私有方法 **/
  /**
   * 初始化图层 
   */
  _initLayer() {
    this._fillLayer = new FillLayer({
      map: this._map,
      minZoom: this._minZoom,
      color: this._color,
      opacity: 0.25,
      outline: true,
      lineColor: this._color, //'#176BC9',
      lineWidth: 2.0,
      lineOpacity: 0.75,
      sourceId: this._sourceId
    });
  }
}