import DataUtils from '../utils/DataUtils';
import CommonUtils from '../utils/CommonUtils';
import LayerProvider from '../geog/LayerProvider';
import GeoJsonProvider from '../geog/GeoJsonProvider';
import BoundaryLayer from '../common/BoundaryLayer';
import DrainageAreaLayer from './DrainageAreaLayer';
import DrainagePointLayer from './DrainagePointLayer';
import ServiceRangeLayer from '../plant/ServiceRangeLayer';

import { getApi } from '../../api/http';

/**
 * 排水分区提供类
 * @alias DrainageAreaProvider
 *
 * @summary <用于排水分区图层加载>
 */
export default class DrainageAreaProvider {
  /**
   * 构造函数
   * @param {Object} options -图层选项
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;

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

    // 排水分区颜色
    this._color = null;

    this._defaultTownIds = null; // 默认街镇ID串

    // 数据
    this._townAreaFC = GeoJsonProvider.getEmptyFC();
    this._plantAreaFC = GeoJsonProvider.getEmptyFC();
    this._pumpAreaFC = GeoJsonProvider.getEmptyFC();
    this._unitAreaFC = GeoJsonProvider.getEmptyFC();

    // 图层
    this._townAreaLayer = null;  // 街镇
    this._plantAreaLayer = null; // 排水系统
    this._pumpAreaLayer = null;  // 排水分区
    this._unitAreaLayer = null;  // 排水单元

    this._samplePointLayer = null;  // 分析点
    this._serviceRangeLayer = null; // 厂服务范围

    this._boundaryLayer = null; // 边界图层
    // 初始化图层
    this._initLayers();
  }

  /** 公有方法 **/
  /**
   * 设置街镇ID串
   * @param {string} ids -街镇ID串
   */
  setTown(ids) {
    this._defaultTownIds = ids;
  }

  /**
   * 设置数据
   * @param {String} type -分区类型
   * @param {String} indexType -指标类型
   * @param {Array} data -分区数据
   * @param {String} townIds -街镇ID字符串(,分隔)
   * @param {Function} callback -回调
   */
  async setData(type,indexType, data, townIds, callback=null) {
    const map = this._map;
    const that = this;

    if (townIds && townIds.length === 0) {
      townIds = null;
    }

    if (type === 'samplepoint') {
      // 厂服务范围
      this._serviceRangeLayer.loadLayer();
      const filter = (townIds && townIds.length > 0)
                     ? ['in', 'town'].push(townIds.split(','))
                     : [];
      this._serviceRangeLayer.setFilter(filter);

      // 分析点
      data.forEach((item) => {
        if(indexType==='bod'){
          item.bod = (item.bod || item.bod === 0) ? (item.bod + ' mg/L') : '-';
          item.cod = (item.cod || item.cod === 0) ? (item.cod + ' mg/L') : '-';
          item.nh3 = (item.nh3 || item.nh3 === 0) ? (item.nh3 + ' mg/L') : '-';
          item.waterLevel = item.waterLevel ? (item.waterLevel + ' m') : '-';
          item.cumulativeFlow = item.cumulativeFlow ? (item.cumulativeFlow + ' m³') : '-';

          item.value = item.bod;
          item.level = item.bodLevel ? item.bodLevel.toString() : '-1';
        }if(indexType==='cod'){
          item.bod = (item.bod || item.bod === 0) ? (item.bod + ' mg/L') : '-';
          item.cod = (item.cod || item.cod === 0) ? (item.cod + ' mg/L') : '-';
          item.nh3 = (item.nh3 || item.nh3 === 0) ? (item.nh3 + ' mg/L') : '-';
          item.waterLevel = item.waterLevel ? (item.waterLevel + ' m') : '-';
          item.cumulativeFlow = item.cumulativeFlow ? (item.cumulativeFlow + ' m³') : '-';

          item.value = item.cod;
          item.level = item.codLevel ? item.codLevel.toString() : '-1';
        }if(indexType==='nh3'){
          item.nh3 = (item.nh3 || item.nh3 === 0) ? (item.nh3 + ' mg/L') : '-';
          item.waterLevel = item.waterLevel ? (item.waterLevel + ' m') : '-';
          item.cumulativeFlow = item.cumulativeFlow ? (item.cumulativeFlow + ' m³') : '-';

          item.value = item.nh3;
          item.level = item.nh3Level ? item.nh3Level.toString() : '-1';
        }if(indexType==='tn'){

          item.tn = (item.tn || item.tn === 0) ? (item.tn + ' mg/L') : '-';
          item.waterLevel = item.waterLevel ? (item.waterLevel + ' m') : '-';
          item.cumulativeFlow = item.cumulativeFlow ? (item.cumulativeFlow + ' m³') : '-';

          item.value = item.tn;
          item.level = item.tnLevel ? item.tnLevel.toString() : '-1';
        }if(indexType==='tp'){

          item.tp = (item.tp || item.tp === 0) ? (item.tp + ' mg/L') : '-';
          item.waterLevel = item.waterLevel ? (item.waterLevel + ' m') : '-';
          item.cumulativeFlow = item.cumulativeFlow ? (item.cumulativeFlow + ' m³') : '-';
          item.value = item.tp;
          item.level = item.tpLevel ? item.tpLevel.toString() : '-1';
        }
      });
      const pointFC = GeoJsonProvider.data2PointFC(data);

      this._samplePointLayer.setData(pointFC);

      // 设置text-field样式
      map.setLayoutProperty(this._samplePointLayer._labelLayerId, 'text-field', ['format',
        ['get', 'name'], { 'font-scale': 1.0 },
        '\n', {},
        ['get', 'value'], { 'font-scale': 1.0 }
      ]);

      if (callback) {
        callback('done');
      }
      return;
    }

    let fc = GeoJsonProvider.getEmptyFC();
    const needQuery = needQueryApi(type);
    if (needQuery) {
      // 获取地图服务查询url
      let url = this._getQueryUrl(type);
      if (!url) {
        if (callback) {
          callback('done');
        }

        return;
      }

      let ids = this._defaultTownIds;
      if (!ids) {
        ids = townIds;
      }
      if (ids) {
        let newIds = CommonUtils.str2Sqlstr(ids);
        if (newIds && newIds.length > 0) {
          url += "&cql_filter=town in (" + newIds + ")";
        }
      }
      // 查询地图服务
      const res = await getApi(url);
      fc = res.data;

      // 更新排水分区要素集合
      updateAreaFC(type, fc);
    } else {
      updateFC(type, fc);
    }

    if (fc && fc.features && fc.features.length > 0) {
      // 更新属性值
      updateProperties(indexType,type, fc);

      let layerId = null, fldName = null;
      switch (type) {
        case 'town': { // 街镇
          this._townAreaLayer.setData(fc);

          layerId = this._townAreaLayer._labelLayerId;
          fldName = 'name';
          break;
        }
        case 'drainsystem': { // 排水系统(水厂服务范围)
          this._plantAreaLayer.setData(fc);

          layerId = this._plantAreaLayer._labelLayerId;
          fldName = 'plant_name';
          break;
        }
        case 'drainregion': { // 排水分区(泵站服务范围)
          this._pumpAreaLayer.setData(fc);

          layerId = this._pumpAreaLayer._labelLayerId;
          fldName = 'pump_name';
          break;
        }
        case 'drainunit': { // 排水单元
          this._unitAreaLayer.setData(fc);

          layerId = this._unitAreaLayer._labelLayerId;
          fldName = 'unit_name';
          break;
        }
        default:
          return;
      } // end of switch (type)

      // 设置text-field样式
      map.setLayoutProperty(layerId, 'text-field', ['format',
        ['get', fldName], { 'font-scale': 1.25 },
        '\n', {},
        ['get', 'value'], { 'font-scale': 1.0 }
      ]);
    }

    if (callback) {
      callback('done');
    }

    /**
     * 是否需要更新
     * @param {String} type -类型
     */
    function needQueryApi(type) {
      switch (type) {
        case 'town':
          return that._townAreaFC.features.length === 0;
        case 'drainsystem':
          return that._plantAreaFC.features.length === 0;
        case 'drainregion':
          return that._pumpAreaFC.features.length === 0;
        case 'drainunit':
          return that._unitAreaFC.features.length === 0;
        default:
          return false;
      }
    }

    /**
     * 更新要素集
     * @param {String} type -类型
     * @param {Object} fc -GeoJSON要素集
     */
    function updateAreaFC(type, fc) {
      switch (type) {
        case 'town': { // 街镇
          that._townAreaFC.features = fc.features;
          break;
        }
        case 'drainsystem': { // 水厂纳污范围
          fc.features = fc.features.filter((feature) => {
            return feature.properties.plant_id ? true : false;
          });
          that._plantAreaFC.features = fc.features;
          break;
        }
        case 'drainregion': { // 泵站纳污范围
          fc.features = fc.features.filter((feature) => {
            return feature.properties.pump_id ? true : false;
          });
          that._pumpAreaFC.features = fc.features;
          break;
        }
        case 'drainunit': { // 排水单元
          fc.features = fc.features.filter((feature) => {
            return feature.properties.unit_code ? true : false;
          });
          that._unitAreaFC.features = fc.features;
          break;
        }
        default:
          break;
      }
    }

    /**
     * 更新要素集
     * @param {String} type -类型
     * @param {Object} fc -GeoJSON要素集
     */
    function updateFC(type, fc) {
      switch (type) {
        case 'town':
          fc.features = that._townAreaFC.features;
          break;
        case 'drainsystem':
          fc.features = that._plantAreaFC.features;
          break;
        case 'drainregion':
          fc.features = that._pumpAreaFC.features;
          break;
        case 'drainunit':
          fc.features = that._unitAreaFC.features;
          break;
        default:
          break;
      }
    }

    /**
     * 更新属性值
     * @param {String} indexType -指标类型
     * @param {String} type -类型
     * @param {Object} fc -GeoJSON要素集
     */
    function updateProperties(indexType,type, fc) {
      let layerFld = null, dataFld = null;
      switch (type) {
        case 'town': {
          layerFld = 'town';
          dataFld = 'townId';
          break;
        }
        case 'drainsystem': {
          layerFld = 'plant_id';
          dataFld = 'plantId';
          break;
        }
        case 'drainregion': {
          layerFld = 'pump_id';
          dataFld = 'pumpId';
          break;
        }
        case 'drainunit': {
          layerFld = 'unit_code';
          dataFld = 'unitId';
          break;
        }
        default:
          return;
      }

      // 过滤数据
      if (townIds) {
        const townIdArr = townIds.split(',');
        fc.features = fc.features.filter((fea) => {
          return townIdArr.indexOf(fea.properties.town) >= 0;
        });
      }

      fc.features.forEach((fea) => {
        const layerFldVal = fea.properties[layerFld];
        const items = data.filter((item) => {
          return (item[dataFld] && item[dataFld] === layerFldVal);
        });

        if (items.length > 0) {
          if(indexType==='bod'){
            fea.properties.bod = (items[0].bod || items[0].bod === 0) ? (items[0].bod + ' mg/L') : '-';
            fea.properties.cod = (items[0].cod || items[0].cod === 0) ? (items[0].cod + ' mg/L') : '-';
            fea.properties.nh3 = (items[0].nh3 || items[0].nh3 === 0) ? (items[0].nh3 + ' mg/L') : '-';
            fea.properties.value = fea.properties.bod;
            fea.properties.level = items[0].bodLevel ? items[0].bodLevel.toString() : '-1';
            fea.properties.analysisType = items[0].analysisType;
            fea.properties[dataFld] = items[0][dataFld];
          }if(indexType==='cod'){
            fea.properties.bod = (items[0].bod || items[0].bod === 0) ? (items[0].bod + ' mg/L') : '-';
            fea.properties.cod = (items[0].cod || items[0].cod === 0) ? (items[0].cod + ' mg/L') : '-';
            fea.properties.nh3 = (items[0].nh3 || items[0].nh3 === 0) ? (items[0].nh3 + ' mg/L') : '-';
            fea.properties.value = fea.properties.cod;
            fea.properties.level = items[0].codLevel ? items[0].codLevel.toString() : '-1';
            fea.properties.analysisType = items[0].analysisType;
            fea.properties[dataFld] = items[0][dataFld];
          }
          if(indexType==='nh3'){
            fea.properties.nh3 = (items[0].nh3 || items[0].nh3 === 0) ? (items[0].nh3 + ' mg/L') : '-';
            fea.properties.value = fea.properties.nh3;
            fea.properties.level = items[0].nh3Level ? items[0].nh3Level.toString() : '-1';
            fea.properties.analysisType = items[0].analysisType;
            fea.properties[dataFld] = items[0][dataFld];
          }
          if(indexType==='tn'){
            fea.properties.tn = (items[0].tn || items[0].tn === 0) ? (items[0].tn + ' mg/L') : '-';
            fea.properties.value = fea.properties.tn;
            fea.properties.level = items[0].tnLevel ? items[0].tnLevel.toString() : '-1';
            fea.properties.analysisType = items[0].analysisType;
            fea.properties[dataFld] = items[0][dataFld];
          }
          if(indexType==='tp'){
            fea.properties.tp = (items[0].tp || items[0].tp === 0) ? (items[0].tp + ' mg/L') : '-';
            fea.properties.value = fea.properties.tp;
            fea.properties.level = items[0].tpLevel ? items[0].tpLevel.toString() : '-1';
            fea.properties.analysisType = items[0].analysisType;
            fea.properties[dataFld] = items[0][dataFld];
          }

        } else {
          fea.properties.bod = '-';
          fea.properties.cod = '-';
          fea.properties.nh3 = '-';
          fea.properties.tn = '-';
          fea.properties.tp = '-';
          fea.properties.value = '-';
          fea.properties.level = '-1';
          fea.properties.analysisType = -1;
          fea.properties[dataFld] = null;
        }
      });
    }
  }

  /**
   * 选择数据
   * @param {String} type -分区类型
   * @param {Object} data -分区数据
   */
  selectData(type, data) {
    if (type === 'samplepoint') return;

    // 获取地图服务查询url
    let url = this._getQueryUrl(type);
    if (!url) return;

    // 获取查询条件
    const cqlFilter = getCqlFilter(type, data);
    if (!cqlFilter) return;

    url += "&cql_filter=" + cqlFilter;
    // 查询地图服务
    getApi(url).then((res) => {
      const fc = res.data;

      this._boundaryLayer.setData(fc);
      // 缩放至要素
      if (fc.features && fc.features.length > 0) {
        this._boundaryLayer.fitBounds(fc.features);
      }
    });

    /**
     * 获取cql_filter
     */
    function getCqlFilter(type, data) {
      switch(type) {
        case 'town':
          return data.townId ? "town='" + data.townId + "'" : null;
        case 'drainsystem':
          return data.plantId ? "plant_id='" + data.plantId + "'" : null;
        case 'drainregion':
          return data.pumpId ? "pump_id='" + data.pumpId + "'" : null;
        case 'drainunit':
          return data.unitId ? "unit_code='" + data.unitId + "'" : null;
        default:
          return null;
      }
    }
  }

  /**
   * 设置筛选器
   * @param {String} type -类型
   * @param {Array} filter -过滤器
   */
  setFilter(type, filter) {
    switch (type) {
      case 'town': { // 街镇
        this._townAreaLayer.setFilter(filter);
        break;
      }
      case 'drainsystem': { // 排水系统(水厂服务范围)
        this._plantAreaLayer.setFilter(filter);
        break;
      }
      case 'drainregion': { // 排水分区(泵站服务范围)
        this._pumpAreaLayer.setFilter(filter);
        break;
      }
      case 'drainunit': { // 排水单元
        this._unitAreaLayer.setFilter(filter);
        break;
      }
      case 'samplepoint': { // 采样点
        this._samplePointLayer.setFilter(filter);
        this._serviceRangeLayer.setFilter(filter);
        break;
      }
      default:
        return;
    }
  }

  /**
   * 加载图层
   * @param {String} type -类型
   */
  loadLayer(type) {
    switch (type) {
      case 'town': // 街镇
        this._townAreaLayer.loadLayer();
        break;
      case 'drainsystem': { // 排水系统(水厂服务范围)
        this._plantAreaLayer.loadLayer();
        break;
      }
      case 'drainregion': { // 排水分区(泵站服务范围)
        this._pumpAreaLayer.loadLayer();
        break;
      }
      case 'drainunit': { // 排水单元
        this._unitAreaLayer.loadLayer();
        break;
      }
      case 'samplepoint': { // 采样点
        this._serviceRangeLayer.loadLayer();
        this._samplePointLayer.loadLayer();
        break;
      }
      default:
        return;
    }
  }

  /**
   * 移除图层
   */
  removeLayer(type) {
    switch (type) {
      case 'town': // 街镇
        this._townAreaLayer.removeLayer();
        break;
      case 'drainsystem': { // 排水系统(水厂服务范围)
        this._plantAreaLayer.removeLayer();
        break;
      }
      case 'drainregion': { // 排水分区(泵站服务范围)
        this._pumpAreaLayer.removeLayer();
        break;
      }
      case 'drainunit': { // 排水单元
        this._unitAreaLayer.removeLayer();
        break;
      }
      case 'samplepoint': { // 采样点
        this._samplePointLayer.removeLayer();
        this._serviceRangeLayer.removeLayer();
        break;
      }
      default:
        return;
    }
  }

  /**
   * 显示/隐藏图层
   * @param {String} type -类型
   * @param {Boolean} isShow -是否显示图层
   */
  showLayer(type, isShow) {
    switch (type) {
      case 'town': { // 街镇
        this._townAreaLayer.showLayer(isShow);
        break;
      }
      case 'drainsystem': { // 排水系统(水厂服务范围)
        this._plantAreaLayer.showLayer(isShow);
        break;
      }
      case 'drainregion': { // 排水分区(泵站服务范围)
        this._pumpAreaLayer.showLayer(isShow);
        break;
      }
      case 'drainunit': { // 排水单元
        this._unitAreaLayer.showLayer(isShow);
        break;
      }
      case 'samplepoint': { // 采样点
        this._samplePointLayer.showLayer(isShow);
        this._serviceRangeLayer.showLayer(isShow);
        break;
      }
      default:
        return;
    }
  }

  /**
   * 判断是否已加载图层
   * @param {String} type -类型
   *
   * @returns {Boolean}
   */
  hasLayer(type) {
    switch (type) {
      case 'town': // 街镇
        return this._townAreaLayer.hasLayer();
      case 'drainsystem': // 排水系统(水厂服务范围)
        return this._plantAreaLayer.hasLayer();
      case 'drainregion': // 排水分区(泵站服务范围)
        return this._pumpAreaLayer.hasLayer();
      case 'drainunit': // 排水单元
        return this._unitAreaLayer.hasLayer();
      case 'samplepoint': // 采样点
        return this._samplePointLayer.hasLayer();
      default:
        return false;
    }
  }

  /**
   * 绑定单击事件
   * @param {String} type -设施类型
   * @param {Function} event -事件函数
   */
  bindClickEvent(type, event) {
    switch (type) {
      case 'town': { // 街镇
        this._townAreaLayer.onClick(event);
        break;
      }
      case 'drainsystem': { // 排水系统(水厂服务范围)
        this._plantAreaLayer.onClick(event);
        break;
      }
      case 'drainregion': { // 排水分区(泵站服务范围)
        this._pumpAreaLayer.onClick(event);
        break;
      }
      case 'drainunit': { // 排水单元
        this._unitAreaLayer.onClick(event);
        break;
      }
      case 'samplepoint': { // 采样点
        this._samplePointLayer.onClick(event);
        break;
      }
      default:
        return;
    }
  }

  /**
   * 绑定事件
   * @param {String} type -设施类型
   * @param {String} name -事件名称
   * @param {Function} event -事件函数
   */
  bindEvent(type, name, event) {
    switch (type) {
      case 'samplepoint': { // 采样点
        this._samplePointLayer.onEvent(name, event);
        break;
      }
      default:
        return;
    }
  }

  /**
   * 移除所有图层
   */
  removeAllLayers() {
    this._townAreaLayer.removeLayer();  // 街镇

    this._plantAreaLayer.removeLayer(); // 排水系统

    this._pumpAreaLayer.removeLayer();  // 排水分区

    this._unitAreaLayer.removeLayer();  // 排水单元

    this._samplePointLayer.removeLayer();  // 分析点
    this._serviceRangeLayer.removeLayer(); // 厂服务范围
  }

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

    // 颜色表达式
    const colorExp = {
      type: 'categorical',
      property: 'level',
      stops: [
        ['1', '#4AAA77'],
        ['2', '#E8C600'],
        ['3', '#FA7A14'],
        ['4', '#FB0003'],
        ['5', '#B30002']
      ],
      default: '#B0C4DE' // E1DFDC
    };
    this._color = colorExp;

    // 街镇
    this._townAreaLayer = new DrainageAreaLayer({
      map: map,
      minzoom: minZoom,
      minzoom_label: minZoom,
      color: colorExp,
      field: 'name',
      textSize: 16,
      sourceId: 'pipe_drainagearea_town'
    });
    this._townAreaLayer.loadLayer();

    // 排水系统
    this._plantAreaLayer = new DrainageAreaLayer({
      map: map,
      minzoom: minZoom,
      minzoom_label: minZoom,
      color: colorExp,
      field: 'plant_name',
      textSize: 14,
      sourceId: 'pipe_drainagearea_plant'
    });
    this._plantAreaLayer.loadLayer();

    // 排水分区
    this._pumpAreaLayer = new DrainageAreaLayer({
      map: map,
      minzoom: minZoom,
      minzoom_label: minZoom + 0.5,
      color: colorExp,
      field: 'pump_name',
      textSize: 13,
      sourceId: 'pipe_drainagearea_pump'
    });
    this._pumpAreaLayer.loadLayer();

    // 排水单元
    this._unitAreaLayer = new DrainageAreaLayer({
      map: map,
      minzoom: minZoom,
      minzoom_label: minZoom + 3.75,
      color: colorExp,
      field: 'unit_name',
      textSize: 12,
      sourceId: 'pipe_drainagearea_unit'
    });
    this._unitAreaLayer.loadLayer();

    // 分析点
    this._samplePointLayer = new DrainagePointLayer({
      map: map,
      minzoom: minZoom,
      minzoom_label: minZoom + 3.25,
      icon: {
        type: 'categorical',
        property: 'level',
        stops: [
          ['1', 'ladle-green'],
          ['2', 'ladle-yellow'],
          ['3', 'ladle-orange'],
          ['4', 'ladle-red'],
          ['5', 'ladle-dull']
        ],
        default: 'ladle-green'
      },
      color: colorExp,
      field: 'name',
      textSize: 11,
      sourceId: 'pipe_drainagearea_point'
    });
    // 厂服务范围
    this._serviceRangeLayer = new ServiceRangeLayer({
      map: map,
      minzoom: minZoom,
      color: '#CDF0E5',
      lineColor: '#8EADF3',
      opacity: 0.5,
      layerId: 'pipe_drainagearea_range'
    });

    // 自定义边界颜色
    let lineColor = map._customStyle ? map._customStyle.boundary_lineColor : '#FFD188';
    // 边界图层
    this._boundaryLayer = new BoundaryLayer({
      map: map,
      minzoom: minZoom,
      color: lineColor,
      width: 2,
      sourceId: 'pipe_drainagearea_boundary',
    });
  }

  /**
   * 获取查询语句
   * @param {String} type -类型
   */
  _getQueryUrl(type) {
    let category = null;
      switch (type) {
        case 'town':
          category = 'town';
          break;
        case 'drainsystem':
          category = 'servicerange-plant';
          break;
        case 'drainregion':
          category = 'servicerange-pump';
          break;
        case 'drainunit':
          category = 'drainunit';
          break;
        default:
          return null;
      }

      // 获取街镇服务接口
      return LayerProvider.getBaseLayerQueryUrl(this._map, category);
  }
}
