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

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

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

    /**
     * 符号位置
     * @type {String}
     * 
     * @summery <取值：point、line、line-center>
     */
    this._placement = DataUtils.default(options.placement, 'point');
    
    /**
     * 符号间距
     * @type {Number}
     * 
     * @summery <在options.placement==='line'时生效>
     */
    this._spacing = DataUtils.default(options.spacing, 250);

    /**
     * 字段名
     * @type {String}
     */
    this._textField = DataUtils.default(options.field, 'label');

    /**
     * 文本大小
     * @type {Number}
     */
    this._textSize = DataUtils.default(options.size, 13);

    /**
     * 文本偏移
     * @type {Array}
     */
    this._textOffset = DataUtils.default(options.offset, [0, 0]);
    
    /**
     * 文本可移动的锚点
     * @type {Array}
     */
    this._textVariableAnchor = DataUtils.default(options.variableAnchor, ['center']);
    
    /**
     * 文本径向偏移
     * @type {Number} 
     */
    this._textRadialOffset = DataUtils.default(options.radialOffset, 0);

    /**
     * 文本旋转角度(顺时针)
     * @type {Number|Array}
     */
    this._textRotate = DataUtils.default(options.rotate, 0);

    /**
     * 文本旋转对齐
     * @type {String} 
     */
    this._textAlignment = DataUtils.default(options.alignment, 'auto');

    /**
     * 图标是否环绕文字
     * @type {Boolean}
     */
    this._around = DataUtils.default(options.around, false);
    
    /**
     * 是否在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_label');

    /**
     * 图层ID
     * @type {String}
     */
    this._layerId = DataUtils.default(options.layerId, this._sourceId);
    
    // 样式属性数组
    this._styleProperties = [];

    // 要素集
    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.isFeature(data)) { 
      // 要素
      fc.features = [data];
    } 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);
  }

  /**
   * 设置绘制属性
   * @param {String} name -属性名称
   * @param {String|Object} value -属性值 
   */
  setPaintProperty(name, value) {
    if (!this.hasLayer()) {
      this._styleProperties.push({ style: 'paint', name: name, value: value });
      return;
    }

    this._map.setPaintProperty(this._layerId, name, value);
  }

  /**
   * 设置布局属性
   * @param {String} name -属性名称
   * @param {String|Object} value -属性值 
   */
  setLayoutProperty(name, value) {
    if (!this.hasLayer()) {
      this._styleProperties.push({ style: 'layout', name: name, value: value });
      return;
    }

    this._map.setLayoutProperty(this._layerId, name, value);
  }

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

    const map = this._map;
    const minZoom = this._minZoom;

    const sourceId = this._sourceId;
    const layerId = this._layerId;
    if (!LayerUtils.hasSource(map, sourceId)) {
      // 添加数据源
      map&&map.addSource(sourceId, {
        type: "geojson",
        data: this._dataUrl || GeoJsonUtils.getEmptyFC()
      });
    }
    
    // 自定义样式
    const customStyle = map&&map._params.customStyle;
    // 自定义字体颜色
    const textColor = customStyle ? customStyle.textColor : '#F8F8FF';
    const haloColor = customStyle ? customStyle.haloColor : '#8B8B8B';
    const haloWidth = customStyle ? customStyle.haloWidth : 0.1;

    // 3D建筑物图层ID
    const buildingLayerId = this._underBuilding 
                            ? map&&map._params.building3DLayerId 
                            : undefined;
    // 添加图层
    map.addLayer({
      type: "symbol",
      id: layerId,
      source: sourceId,
      minzoom: minZoom,
      layout: {
        "symbol-avoid-edges": true,
        "symbol-placement": this._placement,
        "symbol-spacing": this._spacing,
        "text-font": ["Microsoft YaHei"],
        "text-field": "{" + this._textField + "}",
        "text-size": this._textSize,
        "text-offset": this._textOffset,
        "text-justify": "auto",
        "text-max-width": 32,
        "text-rotate": this._textRotate,
        "text-rotation-alignment": this._textAlignment,
        //"text-variable-anchor": this._textVariableAnchor,
        "text-radial-offset": this._textRadialOffset, 
        visibility: "none"
      },
      paint: {
        "text-color": textColor,
        "text-halo-color": haloColor,
        "text-halo-width": haloWidth,
      }
    }, buildingLayerId);
    
    // 图标环绕文组
    if (this._around) {
      map.setLayoutProperty(layerId, 'icon-text-fit', 'both');
    }

    // 设置自定义样式
    if (this._styleProperties.length > 0) {
      this._styleProperties.forEach(prop => {
        switch (prop.style) {
          case 'paint':
            map.setPaintProperty(layerId, prop.name, prop.value);
            break;
          case 'layout':
            map.setLayoutProperty(layerId, prop.name, prop.value);
            break;
          default:
            break;
        }
      });
    }

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

  /**
   * 显示/隐藏图层
   * @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);
  }
}