import DataUtils from "../utils/DataUtils";
import VerifyUtils from "../utils/VerifyUtils";
import IconProvider from "../geog/IconProvider";
import LayerProvider from "../geog/LayerProvider";
import AlarmLayer from '../equipment/AlarmLayer';
import ClusterLayer from '../common/ClusterLayer';
import HeatmapLayer from '../common/HeatmapLayer';
import VideoClusterLayer from '../common/VideoClusterLayer';
import DrainEntityStatsLayer from './DrainEntityStatsLayer';
import DrainUnitLayer from './DrainUnitLayer';

/**
 * 定义排水户管理提供类
 *
 * @alias DrainEntityProvider
 *
 * @summary <用于排水户地图交互>
 */
export default class DrainEntityProvider {
  /**
   * 构造函数
   * @param {Object} options -排水户选项
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;

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

    /**
     * 聚合最大缩放层级
     * @type {Number}
     */
    this._clusterMaxZoom = DataUtils.default(options.clusterMaxZoom, 14);

    /**
     * 聚合半径
     * @type {Number}
     */
    this._clusterRadius = DataUtils.default(options.clusterRadius, 120);

    this._category = 'catalog'; // 排水户类别
    // 显示状态(stats, cluster, heatmap, video)
    this._displayState = null;

    /** 数据源/图层ID **/
    // 排水户点
    this._sourceId = 'pipe_drainer';
    this._videoSourceId = 'pipe_video';

    // 聚合数据源Id
    this._alarmSourceId = this._sourceId + '_alarm'; // 报警点
    this._clusterSourceId = this._sourceId + '_cluster'; // 点聚合
    this._heatmapSourceId = this._sourceId + '_heatmap'; // 热力图
    this._videoClusterSourceId = this._videoSourceId + '_cluster'; // 视频点聚合

    this._alarmLayerId = this._alarmSourceId;
    this._clusterLayerId = this._clusterSourceId;
    this._heatmapLayerId = this._heatmapSourceId;
    this._videoClusterLayerId = this._videoClusterSourceId;

    /** 图层对象 **/
    this._drainUnitLayer = null; // 排水单元

    this._alarmLayer = null;   // 报警点
    this._clusterLayer = null; // 点聚合
    this._heatmapLayer = null; // 热力图
    this._videoClusterLayer = null; // 视频点聚合

    this._statsLayer = null;   // 统计圆

    // 初始化图层
    this._initLayers();
  }

  /** 公有方法 **/
  /**
   * 设置排水户类别
   * @param {String} category -类别
   *
   * @summary <
   * category参数取值: (
   * single-单一符号
   * grade-分级
   * catalog-分类
   * connect-接驳
   * defect-缺陷
   * sumlevel-用水量分级
   * )>
   */
  setCategory(category = 'catalog') {
    this._category = category;
  }

  /**
   * 移除所有图层(销毁时调用)
   */
  removeAllLayers() {
    // 报警点
    this._alarmLayer.removeLayer();

    // 统计圆
    this._statsLayer.removeLayer();
    this._statsLayer.removeSource();

    // 排水单元
    this._drainUnitLayer.removeLayer();
    this._drainUnitLayer.removeSource();

    // 点聚合
    this._clusterLayer.removeLayer();
    this._clusterLayer.removeSource();

    // 热力图
    this._heatmapLayer.removeLayer();
    this._heatmapLayer.removeSource();
  }

  /**
   * 显示/隐藏当前状态图层
   * @param {Boolean} isShow -是否显示
   */
  showCurrentStateLayer(isShow) {
    switch (this._displayState) {
      case 'stats': {
        this._statsLayer.showLayer(isShow);
        break;
      }
      case 'cluster': {
        this._clusterLayer.showLayer(isShow);
        break;
      }
      case 'video': {
        this._videoClusterLayer.showLayer(isShow);
        break;
      }
      case 'heatmap': {
        this._heatmapLayer.showLayer(isShow);
        break;
      }
      default:
        break;
    }
  }

  /**
   * 设置点聚合数据
   * @param {Object|Array|String} data -GeoJson要素集/条件语句
   *
   * @summary <当data参数为String类型时，可以为空，或者是查询语句，例如：town='8'>
   */
  setClusterData(data) {
    this._displayState = 'cluster'; // 点聚合

    // 隐藏其他图层
    this._hideOtherLayers();

    // 判断是否图层字段
    let isLayerField = (!data) || VerifyUtils.isString(data);
    // 获取图标表达式
    let iconExpression = IconProvider.getDrainerIconExpression(this._category, isLayerField);

    // 设置图标
    this._clusterLayer.setIcon(iconExpression);

    // 加载图层
    if (!this._clusterLayer.hasLayer()) {
      this._clusterLayer.loadLayer();
    }
    // 隐藏图层
    this._clusterLayer.showLayer(false);

    if (isLayerField) { // 条件语句
      const map = this._map;
      let source = map.getSource(this._sourceId);
      if (source) {
        let url = source._data + '&cql_filter=' + data;
        // 设置图层查询语句
        this._clusterLayer.setData(url);
      }
    } else {
      // 数据
      this._clusterLayer.setData(data);
    }
  }

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

  /**
   * 过滤热力图数据
   * @param {Object|Array|String} data -GeoJson要素集/条件语句
   *
   * @summary <当data参数为String类型时，可以为空，或者是查询语句，例如：town='8'>
   */
  setHeatmapData(data) {
    this._displayState = 'heatmap'; // 热力图

    // 隐藏其他图层
    this._hideOtherLayers();

    // 加载图层
    if (!this._heatmapLayer.hasLayer()) {
      this._heatmapLayer.loadLayer();
    }
    // 隐藏图层
    this._heatmapLayer.showLayer(false);

    if (!data || VerifyUtils.isString(data)) { // 条件语句
      const map = this._map;
      let source = map.getSource(this._sourceId);
      if (source) {
        let url = source._data + '&cql_filter=' + data;

        // 更新数据源
        LayerProvider.updateSource(map, this._sourceId, url);
      }

      // 显示图层
      this._heatmapLayer.showLayer(true);
    } else {
      // 设置数据
      this._heatmapLayer.setData(data);
    }
  }

  /**
   * 设置视频点聚合数据
   * @param {Object|Array|String} data -GeoJson要素集/条件语句
   *
   * @summary <当data参数为String类型时，可以为空，或者是查询语句，例如：town='8'>
   */
  setVideoClusterData(data) {
    this._displayState = 'video'; // 视频

    // 隐藏其他图层
    this._hideOtherLayers();

    // 判断是否图层字段
    let isLayerField = (!data) || VerifyUtils.isString(data);
    // 获取图标表达式
    let iconExpression = IconProvider.getDrainerIconExpression(this._category, isLayerField);

    // 设置图标
    this._videoClusterLayer.setIcon(iconExpression);

    // 加载图层
    if (!this._videoClusterLayer.hasLayer()) {
      this._videoClusterLayer.loadLayer();
    }
    // 隐藏图层
    this._videoClusterLayer.showLayer(false);

    if (isLayerField) { // 条件语句
      const map = this._map;
      let source = map.getSource(this._videoSourceId);
      if (source) {
        let url = source._data + '&cql_filter=' + data;
        // 设置图层查询语句
        this._videoClusterLayer.setData(url);
      }
    } else {
      // 数据
      this._videoClusterLayer.setData(data);
    }
  }

  /**
   * 添加点聚合数据
   * @param {Object} data -GeoJson要素集
   */
  appendClusterData(data) {
    if (!data ||
        !VerifyUtils.isGeoJsonFC(data) ||
        !data.features || data.features.length === 0) {
      return;
    }

    if (this._displayState === 'cluster') {
      // 添加GeoJSON要素集
      this._clusterLayer.appendData(data);
    } else {
      this._clusterLayer.showLayer(false);
    }
  }

  /**
   * 添加热力图数据
   * @param {Object} data -GeoJson要素集
   */
  appendHeatmapData(data) {
    if (!data ||
        !VerifyUtils.isGeoJsonFC(data) ||
        !data.features || data.features.length === 0) {
      return;
    }

    if (this._displayState === 'heatmap') {
      // 添加GeoJSON要素集
      this._heatmapLayer.appendData(data);
    } else {
      this._heatmapLayer.showLayer(false);
    }
  }

  /**
   * 添加视频点聚合数据
   * @param {Object} data -GeoJson要素集
   */
  appendVideoClusterData(data) {
    if (!data ||
        !VerifyUtils.isGeoJsonFC(data) ||
        !data.features || data.features.length === 0) {
      return;
    }

    if (this._displayState === 'video') {
      // 添加GeoJSON要素集
      this._videoClusterLayer.appendData(data);
    } else {
      this._videoClusterLayer.showLayer(false);
    }
  }

  /**
   * 设置报警点数据
   * @param {Object|Array|String} data -GeoJson要素集/条件语句
   *
   * @summary <当data参数为String类型时，可以为空，或者是查询语句，例如：town='8'>
   */
  setAlarmData(data) {
    this._alarmLayer.setData(data);
  }

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

  /**
   * 设置红线范围数据
   * @param {Array} towns -街镇数组
   */
  setBoundaryData(towns = null) {
    let filter = null;
    if (towns) {
      filter = ['in', 'town']; // 筛选器 ['in', 'town', '8','11']

      towns.forEach(town => {
        filter.push(town.id.toString());
      });
    }

    this._drainUnitLayer.loadLayer();
    if (filter) {
      this._drainUnitLayer.setFilter(filter);
    }
  }

  /**
   * 设置统计数据
   * @param {Object|Array} data -GeoJson要素集/过滤器
   */
  setStatsData(data) {
    this._displayState = 'stats'; // 统计点

    // 隐藏其他图层
    this._hideOtherLayers();

    // 设置数据
    this._statsLayer.setData(data);
  }

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

  /**
   * 判断点(视频)聚合图层是否可见
   *
   * @returns {Boolean}
   */
  isClusterVisible() {
    return (
      this._clusterLayer.isVisible() ||
      this._videoClusterLayer.isVisible()
    );
  }

  /**
   * 获取聚合图层ID
   *
   * @return {String}
   */
  getClusterLayerId() {
    return this._clusterLayer._layerId;
  }

  /**
   * 绑定单击事件
   * @param {String} type -图层类型(stats, cluster, alarm, video)
   * @param {Function} event -事件函数
   */
  onClickEvent(type, event) {
    switch (type) {
      case 'alarm':
        this._alarmLayer.onClick(event);
        break;
      case 'stats':
        this._statsLayer.onClick(event);
        break;
      case 'cluster':
        this._clusterLayer.onClick(event);
        break;
      case 'video':
        this._videoClusterLayer.onClick(event);
        break;
      default:
        break;
    }
  }

  /**
   * 绑定单击事件
   * @param {String} type -图层类型(stats, cluster, alarm, video)
   * @param {String} name -事件名称
   * @param {Function} event -事件函数
   */
  onEvent(type, name, event) {
    switch (type) {
      case 'cluster':
        this._clusterLayer.onEvent(name, event);
        break;
      case 'video':
        this._videoClusterLayer.onEvent(name, event);
        break;
      default:
        break;
    }
  }

  /** 私有方法 **/
  /**
   * 初始化图层
   */
  _initLayers() {
    const map = this._map;
    const minZoom = this._minzoom;

    // 报警点图层
    this._alarmLayer = new AlarmLayer({
      map: map,
      minzoom: minZoom,
      sourceId: this._alarmSourceId,
      layerId: this._alarmLayerId
    });

    // 点聚合图层
    this._clusterLayer = new ClusterLayer({
      map: map,
      minzoom: minZoom,
      icon: 'drain_all',
      clusterMaxzoom: this._clusterMaxZoom,
      clusterRadius: this._clusterRadius,
      sourceId: this._clusterSourceId,
      layerId: this._clusterLayerId
    });

    // 热力图图层
    this._heatmapLayer = new HeatmapLayer({
      map: map,
      minzoom: minZoom,
      sourceId: this._heatmapSourceId,
      layerId: this._heatmapLayerId
    });

    // 视频点聚合图层
    this._videoClusterLayer = new VideoClusterLayer({
      map: map,
      minzoom: minZoom,
      icon: 'drain_all',
      clusterMaxzoom: this._clusterMaxZoom,
      clusterRadius: this._clusterRadius,
      sourceId: this._videoClusterSourceId,
      layerId: this._videoClusterLayerId
    });

    // 统计圆图层
    this._statsLayer = new DrainEntityStatsLayer({
      map: map,
      minzoom: minZoom
    });

    // 排水单元图层
    this._drainUnitLayer = new DrainUnitLayer({
      map: map,
      minzoom: minZoom,
      opacity: 0.35
    });
  }

  /**
   * 隐藏其他图层
   */
  _hideOtherLayers() {
    switch (this._displayState) {
      case 'stats': { // 统计点
        this._clusterLayer.showLayer(false);
        this._videoClusterLayer.showLayer(false);
        this._heatmapLayer.showLayer(false);
        this._drainUnitLayer.showLayer(false);
        break;
      }
      case 'cluster': { // 点聚合
        this._statsLayer.showLayer(false);
        this._videoClusterLayer.showLayer(false);
        this._heatmapLayer.showLayer(false);
        break;
      }
      case 'heatmap': { // 热力图
        this._statsLayer.showLayer(false);
        this._clusterLayer.showLayer(false);
        this._videoClusterLayer.showLayer(false);
        this._drainUnitLayer.showLayer(false);
        break;
      }
      case 'video': { // 视频
        this._statsLayer.showLayer(false);
        this._clusterLayer.showLayer(false);
        this._heatmapLayer.showLayer(false);
        this._drainUnitLayer.showLayer(false);
        break;
      }
      default:
        break;
    }
  }
}
