import * as turf from '@turf/turf';
import DataUtils from '../utils/DataUtils';
import VerifyUtils from '../utils/VerifyUtils';
import BoundaryLayer from '../common/BoundaryLayer';
import MapProvider from './MapProvider';
import GeoJsonProvider from './GeoJsonProvider';

/**
 * 定义边界线提供类
 *
 * @alias AreaBoundaryProvider
 *
 * @summary <用于边界线的缩放及高亮>
 */
export default class AreaBoundaryProvider {
  /**
   * 构造函数
   * @param {Object} options -边界线选项
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;

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

    this._townFeatures = []; // 街镇面要素集合

    // 边界线数据源Id
    this._sourceId = 'base_town_boundary_area';
    this._boundSourceId = 'base_boundary_area';
    // 边界线图层Id
    this._layerId = this._sourceId;
    this._boundLayerId = this._boundSourceId;

    // 边界线图层
    this._boundaryLayer = null;
    // 自定义边界线图层
    this._boundLayer = null;
    // 初始化图层
    this._initLayers();
  }

  /**
   * 缩放至边界
   * @param {Object} data -GeoJSON要素集
   * @param {Number} zoom -缩放层级
   */
  static fitBound(map, data, zoom = null) {
    if (!data) return;

    let fc = null;
    if (VerifyUtils.isGeoJsonFC(data)) {
      fc = data;
    } else if (VerifyUtils.isGeoJsonFeature(data)) {
      fc = GeoJsonProvider.getEmptyFC();
      fc.features = [data];
    }

    if (fc && fc.features && fc.features.length > 0) {
      let xmin = 180.0, ymin = 90.0,
      xmax = -180.0, ymax = -90.0;
      let bbox = [];

      fc.features.forEach(feature => {
        bbox = turf.bbox(feature);

        if (xmin > bbox[0]) xmin = bbox[0];
        if (ymin > bbox[1]) ymin = bbox[1];
        if (xmax < bbox[2]) xmax = bbox[2];
        if (ymax < bbox[3]) ymax = bbox[3];
      });

      if (xmin < xmax && ymin < ymax) {
        bbox = [xmin, ymin, xmax, ymax];
        // 缩放至边界
        MapProvider.fitBounds(map, bbox, zoom);
      }
    }
  }

  /** 公有函数 **/
  /**
   * 设置数据
   * @param {Array} data -GeoJSON要素集
   */
  setData(data) {
    if (!data || !VerifyUtils.isArray(data) ||
        data.length === 0 ||
        !VerifyUtils.isGeoJsonFeature(data[0])) return;

    this._townFeatures = data;

    const fc = GeoJsonProvider.getEmptyFC();
    fc.features = data;
    // 设置数据
    this._boundaryLayer.setData(fc);
  }

  /**
   * 加载图层
   */
  loadLayer() {
    this._boundaryLayer.loadLayer();
  }

  /**
   * 移除图层
   */
  removeLayer() {
    this._boundaryLayer.removeLayer();

    this._boundLayer.removeLayer();
  }

  /**
   * 显示/隐藏图层
   * @param {Boolean} isShow -是否显示
   */
  showLayer(isShow = true) {
    this._boundaryLayer.showLayer(isShow);

    this._boundLayer.showLayer(isShow);
  }

  /**
   * 图层是否已加载
   *
   * @returns {Boolean}
   */
  hasLayer() {
    return this._boundaryLayer.hasLayer();
  }

  /**
   * 是否有街镇要素集合
   *
   * @returns {Boolean}
   */
  hasData() {
    return (this._townFeatures.length > 0);
  }

  /**
   * 是否选择了所有街镇边界
   * @param {Array} towns -街镇集合
   */
  isSelectAll(towns) {
    return (
      this._townFeatures.length === 0 ||
      this._townFeatures.length == towns.length
    );
  }

  /**
   * 高亮边界
   * @param {Array|Object} towns -街镇集合/对象
   *
   * @summary <towns参数: [{id: id, name: name}, ...]>
   */
  highlightBounds(towns) {
    // 隐藏图层
    this.showLayer(false);

    if (!towns) return;

    if (VerifyUtils.isObject(towns)) {
      towns = [towns];
    }
    if (towns.length < 1)
      return;

    // 获取过滤条件
    let filter = this._getFilter('area_code', towns);

    // 过滤图层
    this._boundaryLayer.setFilter(filter);
    this._boundaryLayer.showLayer(true);
  }

  /**
   * 缩放至边界
   * @param {Array|Object} towns -街镇集合/对象
   *
   * @summary <towns参数: [{id: id, name: name}, ...]>
   */
  fitBounds(towns) {
    if (!towns) return;

    if (VerifyUtils.isObject(towns)) {
      towns = [towns];
    }
    if (towns.length < 1)
      return;

    const selFeatures = this._townFeatures.filter(feature => {
      return isTownExist(feature.properties.area_code);
    });

    // 缩放至边界
    this._boundaryLayer.fitBounds(selFeatures);

    /**
     * 判断街镇是否存在
     * @param id -街镇Id
     * @returns {Boolean}
     */
    function isTownExist(id) {
      if (towns.find(item => item.id.toString() === id.toString())) {
        return true;
      }

      return false;
    }
  }

  /** 私有函数 **/
  /**
   * 初始化图层
   */
  _initLayers() {
    // 自定义边界颜色
    let lineColor = map._customStyle ? map._customStyle.boundary_lineColor : '#FFD188';

    // 初始化边界线图层
    this._boundaryLayer = new BoundaryLayer({
      map: this._map,
      minzoom: this._minzoom,
      color: lineColor,
      width: 2,
      sourceId: this._sourceId,
      layerId: this._layerId
    });

    this._boundLayer = new BoundaryLayer({
      map: this._map,
      minzoom: this._minzoom,
      color: lineColor,
      width: 1.5,
      opacity: 0.5,
      sourceId: this._boundSourceId,
      layerId: this._boundLayerId
    });
  }

  /**
   * 获取图层过滤条件集合
   * @param {String} fld  -字段名
   * @param {Array} towns -街镇集合
   *
   * @returns {Array} 过滤条件集合
   */
  _getFilter(fld, towns) {
    let filter = [];

    /**
     * 对象数组转字符串数组
     * @param {Array} arr
     */
    function toStrArr(arr) {
      let strArr = [];
      arr.forEach((item) => {
        strArr.push(item.id.toString());
      });

      return strArr;
    }

    if (towns.length > 0) {
      filter = ['in', fld];
      filter.push.apply(filter, toStrArr(towns));
    }

    return filter;
  }
}
