import DataUtils from "../utils/DataUtils";
import VerifyUtils from "../utils/VerifyUtils";
import GeoJsonUtils from "../utils/GeoJsonUtils";
import LayerUtils from "../utils/LayerUtils";

/**
 * 定义热力图图层
 * @alias HeatmapLayer
 * 
 * @summary <用于热力图图层加载>
 */
export default class HeatmapLayer {
  /**
   * 构造函数
   * @param {Object} options -图层选项
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;

    /**
     * 最小缩放层级
     * @type {Number}
     */
    this._minZoom = DataUtils.default(options.minZoom, 9);

    /**
     * 权重
     * @type {Number} 
     */
    this._weight = DataUtils.default(options.weight, 0.1);

    this._radius = DataUtils.default(options.radius, 5);

    this._maxRadius = DataUtils.default(options.maxRadius, 25);

    /**
     * 中心点
     * @type {Number[]}
     */
    this._center = DataUtils.default(options.center, undefined);
 
    /**
     * 是否在3D建筑物图层下面
     * @type {Boolean}
     */
    this._underBuilding = DataUtils.default(options.underBuilding, false);
 
    /**
     * 筛选器
     * @type {Array} 
     */
    this._filter = DataUtils.default(options.filter, undefined);

    /**
     * 数据服务地址
     * @type {String} 
     */
    this._dataUrl = DataUtils.default(options.dataUrl, undefined);

    /**
     * 数据源ID
     * @type {String}
     */
    this._sourceId = DataUtils.default(options.sourceId, 'point_heatmap');

    /**
     * 图层ID
     * @type {String}
     */
    this._layerId = DataUtils.default(options.layerId, this._sourceId);
    
    // 要素集
    this._fc = GeoJsonUtils.getEmptyFC();
  }

  /** 公有方法 **/
  /**
   * 设置数据
   * @param {Object|Array} data -GeoJson要素集/要素列表/点位数组
   * 
   * @summary <data参数：
   *   Object - GeoJson要素集
   *   Array - GeoJson要素数组/点位数组(包含longitude/lng, latitude/lat字段)
   * >
   */
   setData(data) {
    // 加载图层
    if (!this.hasLayer()) {
      this.loadLayer();
    }

    let fc = GeoJsonUtils.getEmptyFC();

    if (VerifyUtils.isFeatureCollection(data)) { 
      // 要素集
      if (data.features && data.features.length > 0) {
        fc.features = data.features;
      }
    } else if (VerifyUtils.isArray(data) && data.length > 0) {
      if (VerifyUtils.isFeature(data[0])) {
        // 要素集合
        fc.features = data;
      } else { 
        // 点位数组
        fc = GeoJsonUtils.array2PointFC(data);
      }
    }

    this._fc.features = [];
    this._fc.features = fc.features;

    // 更新数据源
    LayerUtils.updateSource(this._map, this._sourceId, fc);
    // 显示图层
    this.showLayer(true);
  }

  /**
   * 设置筛选器
   * @param {Array} filter -筛选器
   */
  setFilter(filter) {
    if (!this.hasLayer()) return;

    // 空数组
    if (VerifyUtils.isArray(filter) && filter.length === 0) {
      filter = null;
    }

    let newFilter = null;
    if (this._filter) {
      newFilter = this._filter.length === 1
                  ? ['all', this._filter]
                  : [].concat(this._filter);
    }

    if (filter) {
      if (!newFilter) {
        newFilter = filter;
      } else {
        newFilter.push(filter);
      }
    }

    // 设置筛选器
    this._map.setFilter(this._layerId, newFilter);
  }

  /**
   * 加载图层
   */
  loadLayer() {
    if (this.hasLayer()) return;

    const map = this._map;
    const minZoom = this._minZoom;
    const maxZoom = map.getMaxZoom();

    const sourceId = this._sourceId;
    if (!LayerUtils.hasSource(map, sourceId)) {
      // 添加数据源
      map&&map.addSource(sourceId, {
        type: "geojson",
        data: this._dataUrl || GeoJsonUtils.getEmptyFC()
      });
    }

    // 3D建筑物图层ID
    const buildingLayerId = this._underBuilding 
                            ? map._params.building3DLayerId 
                            : undefined;
    // 添加图层
    map.addLayer({
      type: "heatmap",
      id: this._layerId,
      source: sourceId,
      minzoom: minZoom,
      layout: {
        visibility: "none"
      },
      paint: {
        "heatmap-weight": this._weight,
        "heatmap-intensity": [
          "interpolate", ["linear"], ["zoom"],
          minZoom, 1,
          maxZoom, 5
        ],
        "heatmap-color": [
          "interpolate", ["linear"], ["heatmap-density"],
          0, "rgba(255,255,255,0)",
          0.2, "rgba(0,0,255,0.5)",
          0.4, "rgba(32,178,170,0.5)",
          0.6, "rgba(0,255,0,0.5)",
          0.9, "rgba(255,255,0,0.5)",
          1, "rgba(255,0,0,0.5)"
        ],
        // Adjust the heatmap radius by zoom level
        "heatmap-radius": [
          "interpolate", ["linear"], ["zoom"],
          //minZoom, 35,
          //maxZoom, 75
          minZoom, this._radius,
          maxZoom, this._maxRadius
        ],
        // Transition from heatmap to circle layer by zoom level
        "heatmap-opacity": [
          "interpolate", ["linear"], ["zoom"],
          minZoom, 1,
          maxZoom, 0.5
        ]
      }
    }, buildingLayerId);

    // 筛选器
    if (this._filter) {
      map.setFilter(this._layerId, this._filter);
    }

    // 定位中心点
    if (this._center && this._center.length === 2) {
      map.jumpTo({
        center: this._center,
        zoom: minZoom
      });
    }
  }

  /**
   * 显示/隐藏图层
   * @param {Boolean} show -是否显示
   */
  showLayer(show = true) {
    LayerUtils.showLayer(this._map, this._layerId, show);
  }

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

  /**
   * 移除图层 
   */
  removeLayer() {
    LayerUtils.removeLayer(this._map, this._layerId);
    this._fc.features = [];
  }

  /**
   * 移除数据源
   */
  removeSource() {
    LayerUtils.removeSource(this._map, this._sourceId);
  }
}