import DataUtils from '../utils/DataUtils';
import VerifyUtils from '../utils/VerifyUtils';
import MapProvider from '../geog/MapProvider';
import LayerProvider from '../geog/LayerProvider';
import GeoJsonProvider from '../geog/GeoJsonProvider';
import SimpleMarkerLayer from '../common/SimpleMarkerLayer';
import SimpleLineLayer from '../common/SimpleLineLayer';
import SimpleFillLayer from '../common/SimpleFillLayer';

/**
 * 查询与结果图层
 * @alias QueryResultsLayer
 *
 * @summary <用于属性/空间查询与结果图层的加载>
 */
export default class QueryResultsLayer {
  /**
   * 构造函数
   * @param {Object} options -图层选项
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;

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

    /**
     * 是否查询
     * @type {Boolean}
     */
    this._isQuery = DataUtils.default(options.isQuery, true);

    /** 样式 **/
    // 点图标
    this._resultIcon = 'busi_result';
    this._selectIcon = 'busi_selection';

    // 线样式
    this._lineWidth = this._isQuery ? 2.5 : 5;
    this._lineOpacity = this._isQuery ? 0.5 : 0.75;
    this._lineColor = '#176BC9';
    this._lineSelectColor = '#DC143C';
    // 面样式
    this._fillOpacity = 0.25;
    this._fillColor = '#00FFF0';
    this._fillSelectColor = '#DC143C';

    /** 要素集 **/
    this._dotFC = GeoJsonProvider.getEmptyFC();      // 自定义点(结果)
    this._pointFC = GeoJsonProvider.getEmptyFC();    // 点
    this._polylineFC = GeoJsonProvider.getEmptyFC(); // 折线
    this._polygonFC = GeoJsonProvider.getEmptyFC();  // 多边形

    this._selectFeature = null;  // 选中的要素

    /** 数据源/图层ID **/
    // 数据源ID
    this._dotSourceId = 'dot_results'; // 自定义点(结果)数据源ID
    this._markerSourceId = this._isQuery ? 'point_query' : 'marker_results'; // 点
    this._lineSourceId = this._isQuery ? 'polyline_query' : 'line_results';  // 线
    this._fillSourceId = this._isQuery ? 'polygon_query' : 'fill_results';   // 多边形
    // 图层ID
    this._dotLayerId = this._dotSourceId; // 自定义点(结果)图层ID
    this._markerLayerId = this._markerSourceId; // 点
    this._lineLayerId = this._lineSourceId;     // 线
    this._fillLayerId = this._fillSourceId;     // 多边形

    /** 图层对象 **/
    this._dotLayer = null;    // 自定义点(结果)图层
    this._markerLayer = null; // 点
    this._lineLayer = null;   // 线
    this._fillLayer = null;   // 多边形
  }

  /**
   * 设置数据
   * @param {Object|Array} data -GeoJSON要素集/要素/数据
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  setData(data, type) {
    if (!data || !type) return;

    // 初始化结果图层
    this._initLayer(type);

    // 设置数据
    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        this._dotFC.features = [];
        // 设置数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._dotFC.features = data.features;
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._dotFC.features = [ data ];
        } else if (VerifyUtils.isArray(data) || VerifyUtils.isObject(data)) {
          const fc = GeoJsonProvider.data2PointFC(data);
          this._dotFC.features = fc.features;
        }

        this._dotLayer.setData(this._dotFC);
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        this._pointFC.features = [];
        // 设置数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._pointFC.features = data.features;
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._pointFC.features = [ data ];
        } else if (VerifyUtils.isArray(data) || VerifyUtils.isObject(data)) {
          const fc = GeoJsonProvider.data2PointFC(data);
          this._pointFC.features = fc.features;
        }

        this._markerLayer.setData(this._pointFC);
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        this._polylineFC.features = [];
        // 设置数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._polylineFC.features = data.features;
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._polylineFC.features = [ data ];
        }

        this._lineLayer.setData(this._polylineFC);
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        this._polygonFC.features = [];
        // 设置数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._polygonFC.features = data.features;
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._polygonFC.features = [ data ];
        }

        this._fillLayer.setData(this._polygonFC);
        break;
      }
      default:
        break;
    }
  }

  /**
   * 添加数据
   * @param {Array|Object} data -GeoJSON要素集/要素/数据
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  appendData(data, type) {
    if (!data || !type) return;

    // 初始化结果图层
    this._initLayer(type);

    // 设置数据
    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        // 添加数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._dotFC.features = this._dotFC.features.concat(data.features);
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._dotFC.features.push(data);
        } else if (VerifyUtils.isArray(data) || VerifyUtils.isObject(data)) {
          const fc = GeoJsonProvider.data2PointFC(data);
          this._dotFC.features = this._dotFC.features.concat(fc.features);
        }

        this._dotLayer.setData(this._dotFC);
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        // 添加数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._pointFC.features = this._pointFC.features.concat(data.features);
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._pointFC.features.push(data);
        } else if (VerifyUtils.isArray(data) || VerifyUtils.isObject(data)) {
          const fc = GeoJsonProvider.data2PointFC(data);
          this._pointFC.features = this._pointFC.features.concat(fc.features);
        } else {
          return;
        }

        this._markerLayer.setData(this._pointFC);
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        // 添加数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._polylineFC.features = this._polylineFC.features.concat(data.features);
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._polylineFC.features.push(data);
        } else {
          return;
        }

        this._lineLayer.setData(this._polylineFC);
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        // 添加数据
        if (VerifyUtils.isGeoJsonFC(data)) {
          this._polygonFC.features = this._polygonFC.features.concat(data.features);
        } else if (VerifyUtils.isGeoJsonFeature(data)) {
          this._polygonFC.features.push(data);
        } else {
          return;
        }

        this._fillLayer.setData(this._polygonFC);
        break;
      }
      default:
        break;
    }
  }

  /**
   * 更新要素数据
   * @param {String} data -GeoJSON要素集/要素
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  updateData(data, type) {
    let fc = null;
    let sourceId = null;

    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        fc = this._dotFC;
        sourceId = this._dotSourceId;
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        fc = this._pointFC;
        sourceId = this._markerSourceId;
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        fc = this._polylineFC;
        sourceId = this._lineSourceId;
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        fc = this._polygonFC;
        sourceId = this._fillSourceId;
        break;
      }
      default:
        break;
    }

    if (!fc || !sourceId) return;

    let newFeature = null;
    // 获取要素
    if (VerifyUtils.isGeoJsonFC(data)) {
      newFeature = data.features[0];
    } else if (VerifyUtils.isGeoJsonFeature(data)) {
      newFeature = data;
    }
    if (!newFeature) return;

    // 查询要素列表
    const features = fc.features.filter(fea => {
      return fea.id = newFeature.id;
    });

    // 更新属性和坐标
    if (features.length > 0) {
      features[0].properties = newFeature.properties;
      features[0].geometry.coordinates = newFeature.geometry.coordinates;

      LayerProvider.updateSource(this._map, sourceId, fc);
    }
  }

  /**
   * 是否存在要素数据
   * @param {String} fid -要素ID
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  hasData(fid, type) {
    let fc = null;

    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        fc = this._dotFC;
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        fc = this._pointFC;
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        fc = this._polylineFC;
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        fc = this._polygonFC;
        break;
      }
      default:
        break;
    }

    if (!fc) return false;

    return fc.features.some(fea => {
      return fea.id === fid;
    });
  }

  /**
   * 是否存在属性数据
   * @param {String} field -属性字段名
   * @param {String} value -属性字段值
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  hasPropertyData(field, value, type) {
    let fc = null;

    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        fc = this._dotFC;
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        fc = this._pointFC;
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        fc = this._polylineFC;
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        fc = this._polygonFC;
        break;
      }
      default:
        break;
    }

    if (!fc) return false;

    return fc.features.some(fea => {
      return fea.properties[field] === value;
    });
  }

  /**
   * 获取要素数据
   * @param {String} fid -要素ID
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  getData(fid, type) {
    let fc = null;

    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        fc = this._dotFC;
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        fc = this._pointFC;
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        fc = this._polylineFC;
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        fc = this._polygonFC;
        break;
      }
      default:
        break;
    }

    if (!fc) return null;

    const features =  fc.features.filter(fea => {
      return fea.id === fid;
    });

    return features.length > 0 ? features[0] : null;
  }

  /**
   * 删除要素数据
   * @param {String} fid -要素ID
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  deleteData(fid, type) {
    let fc = null;
    let sourceId = null;

    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        fc = this._dotFC;
        sourceId = this._dotSourceId;
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        fc = this._pointFC;
        sourceId = this._markerSourceId;
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        fc = this._polylineFC;
        sourceId = this._lineSourceId;
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        fc = this._polygonFC;
        sourceId = this._fillSourceId;
        break;
      }
      default:
        break;
    }

    if (!fc || !sourceId) return;

    // 过滤要素列表
    const features = fc.features.filter(fea => {
      return (fea.id != fid && fea.properties.rangeId != fid);
    });

    // 更新要素列表
    fc.features = features;
    LayerProvider.updateSource(this._map, sourceId, fc);
  }

  /**
   * 选择数据
   * @param {String} fid -要素ID
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  selectData(fid, type) {
    // 清除选中
    this.clearSelection(type);

    if (!fid || !type) return;

    let fc = null;
    let sourceId = null;

    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        fc = this._dotFC;
        sourceId = this._dotSourceId;
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        fc = this._pointFC;
        sourceId = this._markerSourceId;
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        fc = this._polylineFC;
        sourceId = this._lineSourceId;
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        fc = this._polygonFC;
        sourceId = this._fillSourceId;
        break;
      }
      default:
        return;
    }

    let selFeature = null;
    // 选中要素
    for (let i = 0; i < fc.features.length; i++) {
      const feature = fc.features[i];
      if (feature.id === fid) {
        selFeature = feature;
        break;
      }
    }

    if (selFeature) {
      selFeature.properties.select = 1;

      this._selectFeature = selFeature;
      // 更新数据源
      LayerProvider.updateSource(this._map, sourceId, fc);

      const selFC = GeoJsonProvider.getEmptyFC();
      selFC.features = [selFeature];
      // 缩放至要素
      MapProvider.zoomToFeatures(this._map, selFC, 19);
    }
  }

  /**
   * 清除选中
   */
  clearSelection(type) {
    if (!this._selectFeature) return;

    // 更新选中属性
    this._selectFeature.properties.select = 0;

    let fc = null;
    let layer = null;
    switch (type.toLowerCase()) {
      case 'dot': { // 自定义点
        fc = this._dotFC;
        layer = this._dotLayer;
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        fc = this._pointFC;
        layer = this._markerLayer;
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        fc = this._polylineFC;
        layer = this._lineLayer;
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        fc = this._polygonFC;
        layer = this._fillLayer;
        break;
      }
      default:
        return;
    }
    // 更新数据
    layer.setData(fc);

    this._selectFeature = null;
  }

  /**
   * 清除所有数据
   */
  clearData() {
    // 自定义点图层
    if (this._dotLayer) {
      this._dotFC.features = [];
      this._dotLayer.setData(this._dotFC);
    }

    // 点图层
    if (this._markerLayer) {
      this._pointFC = GeoJsonProvider.getEmptyFC();
      this._markerLayer.setData(this._pointFC);
    }
    // 线图层
    if (this._lineLayer) {
      this._polylineFC = GeoJsonProvider.getEmptyFC();
      this._lineLayer.setData(this._polylineFC);
    }
    // 填充图层
    if (this._fillLayer) {
      this._polygonFC = GeoJsonProvider.getEmptyFC();
      this._fillLayer.setData(this._polygonFC);
    }
  }


  /**
   * 获取图层ID
   * @param {String} type -几何类型(取值：Point、LineString、Polygon)
   */
  getLayerId(type) {
    switch (type.toLowerCase()) {
      case 'point':
      case 'multipoint': { // 点/多点
        return this._markerLayerId;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        return this._lineLayerId;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        return this._fillLayerId;
      }
      default:
        return null;
    }
  }

  /**
   * 移除图层
   */
  removeLayer() {
    // 自定义点图层
    if (this._dotLayer) {
      this._dotLayer.removeLayer();
      this._dotLayer.removeSource();
    }

    // 点图层
    if (this._markerLayer) {
      this._markerLayer.removeLayer();
      this._markerLayer.removeSource();
    }
    // 线图层
    if (this._lineLayer) {
      this._lineLayer.removeLayer();
      this._lineLayer.removeSource();
    }
    // 填充图层
    if (this._fillLayer) {
      this._fillLayer.removeLayer();
      this._fillLayer.removeSource();
    }
  }

  /**
   * 显示/隐藏图层
   * @param {Boolean} isShow -是否显示
   */
  showLayer(isShow) {
    // 自定义点图层
    if (this._dotLayer) {
      this._dotLayer.showLayer(isShow);
    }

    // 点图层
    if (this._markerLayer) {
      this._markerLayer.showLayer(isShow);
    }
    // 线图层
    if (this._lineLayer) {
      this._lineLayer.showLayer(isShow);
    }
    // 填充图层
    if (this._fillLayer) {
      this._fillLayer.showLayer(isShow);
    }
  }

  /** 私有方法 **/
  /**
   * 初始化结果图层
   * @param {String} type -几何类型(取值：Point、LineString、Polygon; and Dot)
   */
  _initLayer(type) {
    const map = this._map;
    const minZoom = this._minzoom;

    switch (type.toLowerCase()) {
      case 'dot': {
        if (!this._dotLayer) { // 自定义点
          // 创建自定义点图层
          this._dotLayer = new SimpleMarkerLayer({
            map: map,
            minzoom: minZoom,
            icon: {
              type: 'categorical',
              property: 'select',
              stops: [
                [0, this._resultIcon],
                [1, this._selectIcon]
              ],
              default: this._resultIcon
            },
            sourceId: this._dotSourceId,
            layerId: this._dotLayerId
          });
        }
        break;
      }
      case 'point':
      case 'multipoint': { // 点/多点
        if (!this._markerLayer) {
          // 创建点图层
          this._markerLayer = new SimpleMarkerLayer({
            map: map,
            minzoom: minZoom,
            icon: {
              type: 'categorical',
              property: 'select',
              stops: [
                [0, this._resultIcon],
                [1, this._selectIcon]
              ],
              default: this._resultIcon
            },
            sourceId: this._markerSourceId,
            layerId: this._markerLayerId
          });
        }
        break;
      }
      case 'linestring':
      case 'multilinestring': { // 折线/多折线
        if (!this._lineLayer) {
          // 创建线图层
          this._lineLayer = new SimpleLineLayer({
            map: map,
            minzoom: minZoom,
            color: {
              type: 'categorical',
              property: 'select',
              stops: [
                [0, this._lineColor],
                [1, this._lineSelectColor]
              ],
              default: this._lineColor
            },
            width: this._lineWidth,
            fixed: true,
            opacity: [
              'match',
              ['get', 'method'],
              'buffer', 0,
              this._lineOpacity
            ],
            sourceId: this._lineSourceId,
            layerId: this._lineLayerId
          });
        }
        break;
      }
      case 'polygon':
      case 'multipolygon': { // 多边形/多多边形
        if (!this._fillLayer) {
          // 创建面图层
          this._fillLayer = new SimpleFillLayer({
            map: map,
            minzoom: minZoom,
            color: {
              type: 'categorical',
              property: 'select',
              stops: [
                [0, this._fillColor],
                [1, this._fillSelectColor]
              ],
              default: this._fillColor
            },
            opacity: this._fillOpacity,
            outline: true,
            lineColor: {
              type: 'categorical',
              property: 'select',
              stops: [
                [0, this._lineColor],
                [1, this._lineSelectColor]
              ],
              default: this._lineColor
            },
            lineWidth: 2.5,
            lineOpacity: this._lineOpacity,
            sourceId: this._fillSourceId,
            layerId: this._fillLayerId
          });
        }
        break;
      }
      default:
        break;
    }
  }
}
