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

/**
 * 定义GeoJSON方法提供类
 */
export default class GeoJsonProvider {
  constructor() { }

  /**
   * 获取空要素集合
   *
   * @returns {Object} GeoJson根对象
   */
  static getEmptyFC() {
    return {
      type: 'FeatureCollection',
      features: []
    };
  }

  /**
   * 获取空要素
   *
   * @returns {Object} GeoJson要素对象
   */
  static getEmptyFeature(type) {
    return {
      type: 'Feature',
      properties: {},
      geometry: {
        type: type,
        coordinates: []
      }
    };
  }

  /**
   * 获取要素
   * @param {Object} geometry -几何图形
   * @param {Object} properties -属性
   */
  static getFeature(geometry, properties = {}) {
    if (!geometry) return null;

    return {
      id: properties.id,
      type: 'Feature',
      geometry: geometry,
      properties: properties || {}
    };
  }

  /**
   * 获取点要素
   * @param {Number[]} lonLat -经纬度
   * @param {Object} props -属性
   * @summary <lonlat参数: [lon, lat]>
   *
   * @returns {Object} GeoJson点要素对象
   */
  static getPointFeature(lonLat, props = null) {
    let fea = this.getEmptyFeature('Point');
    // 几何图形
    if (lonLat && lonLat.length > 1) {
      fea.geometry.coordinates = lonLat;
    }
    // 属性
    if (props) {
      fea.properties = props;
    }

    return fea;
  }

  /**
   * 获取折线要素
   * @param {Number[][]} lonLats -经纬度数组
   * @param {Object} props -属性
   * @summary <lonlats参数: [[lon, lat], [lon2, lat2],...]>
   *
   * @returns {Object} GeoJson折线要素对象
   */
  static getLineStringFeature(lonLats, props = null) {
    let fea = this.getEmptyFeature('LineString');
    // 几何图形
    if (lonLats && lonLats.length > 1) {
      fea.geometry.coordinates = lonLats;
    }
    // 属性
    if (props) {
      fea.properties = props;
    }

    return fea;
  }

  /**
   * 获取多边形要素
   * @param {Number[][][]} rings -环数组
   * @param {Object} props -属性
   * @summary <rings参数: [[[lon, lat],[lon2, lat2],...],
   *                       [[lon, lat],[lon2, lat2],...],
   *                       ...] />
   *
   * @returns {Object} GeoJson多边形要素对象
   */
  static getPolygonFeature(rings, props = null) {
    let fea = this.getEmptyFeature('Polygon');
    // 几何图形
    if (rings && rings.length > 0) {
      fea.geometry.coordinates = rings;
    }
    // 属性
    if (props) {
      fea.properties = props;
    }

    return fea;
  }

  /**
   * 获取多点要素
   * @param {Number[]} lonLats -经纬度数组
   * @param {Object} props -属性
   * @summary <lonlats参数: [[lon, lat], [lon2, lat2],...]>
   *
   * @returns {Object} GeoJson点要素对象
   */
  static getMultiPointFeature(lonLats, props = null) {
    let fea = this.getEmptyFeature('MultiPoint');
    // 几何图形
    if (lonLats && lonLats.length > 0) {
      fea.geometry.coordinates = lonLats;
    }
    // 属性
    if (props) {
      fea.properties = props;
    }

    return fea;
  }

  /**
   * 获取多折线要素
   * @param {Number[][]} lineStrings -折线数组
   * @param {Object} props -属性
   * @summary <lineStrings参数: [[[lon, lat],[lon2, lat2],...],
   *                             [[lon, lat],[lon2, lat2],...],
   *                             ...] />
   *
   * @returns {Object} GeoJson多折线要素对象
   */
  static getMultiLineStringFeature(lineStrings, props = null) {
    let fea = this.getEmptyFeature('MultiLineString');
    // 几何图形
    if (lineStrings && lineStrings.length > 0) {
      fea.geometry.coordinates = lineStrings;
    }
    // 属性
    if (props) {
      fea.properties = props;
    }

    return fea;
  }

  /**
   * 获取多多边形要素
   * @param {Number[][][]} polygons -多边形数组
   * @param {Object} props -属性
   * @summary <polygons参数: [[[[lon, lat],[lon2, lat2],...],[[lon, lat],[lon2, lat2],...],...],
   *                          [[[lon, lat],[lon2, lat2],...],[[lon, lat],[lon2, lat2],...],...],
   *                          ...]>
   *
   * @returns {Object} GeoJson多多边形要素对象
   */
  static getMultiPolygonFeature(polygons, props = null) {
    let fea = this.getEmptyFeature('MultiPolygon');
    // 几何图形
    if (polygons && polygons.length > 0) {
      fea.geometry.coordinates = polygons;
    }
    // 属性
    if (props) {
      fea.properties = props;
    }

    return fea;
  }

  /**
   * 克隆要素
   * @param {Object} feature -原要素
   *
   * @returns {Object}
   */
  static cloneFeature(feature) {
    if (!feature) return null;

    let newFea = this.getEmptyFeature(feature.geometry.type);
    // 拷贝坐标数组
    let [...coordinates] = feature.geometry.coordinates;
    newFea.geometry.coordinates = coordinates;

    for (let key in feature.properties) {
      newFea.properties[key] = feature.properties[key];
    }

    return newFea;
  }

  /**
   * JSON数组转点要素集合
   * @param {Array | Object} data -JSON集合
   *
   * @returns {Object}
   */
  static data2PointFC(data) {
    let fc = this.getEmptyFC();

    if (data) {
      if (VerifyUtils.isArray(data)) {
        fc.features = data.map((item) => {
          let lon = item.gisLng || item.lng || item.longitude || item.lon;
          let lat = item.gisLat || item.lat || item.latitude;

          // 获取点要素
          return this.getPointFeature([lon, lat], item);
        });
      } else if (VerifyUtils.isObject(data)) {
        let lon = data.gisLng || data.lng || data.longitude;
        let lat = data.gisLat || data.lat || data.latitude;

        // 获取点要素
        let fea = this.getPointFeature([lon, lat], data);
        fc.features = [fea];
      }
    }

    return fc;
  }

  /**
   * 点要素转多边形要素
   * @param {Object|Array} data -GeoJSON要素/经纬度
   *
   * @returns {Object}
   */
  static point2PolygonFeature(data) {
    let feature = null;
    if (VerifyUtils.isGeoJsonFC(data)) {
      feature = data.features[0];
    } else if (VerifyUtils.isGeoJsonFeature(data)) {
      feature = data;
    } else if (VerifyUtils.isArray(data)) {
      feature = this.getPointFeature(data);
    }
    if (!feature) return null;

    // 点查询转换为小矩形查询
    let lonLat = feature.geometry.coordinates;
    let lon = lonLat[0], lat = lonLat[1];
    let os = 0.00001;

    let ring = [
      [lon - os, lat - os],
      [lon - os, lat + os],
      [lon + os, lat + os],
      [lon + os, lat - os],
      [lon - os, lat - os]
    ];

    return this.getPolygonFeature([ring], feature.properties);
  }

  /**
   * 要素集生成UUID属性
   * @param {Object} fc -GeoJSON要素集
   */
  static geneUUID(fc) {
    if (!fc || !fc.features || fc.features.length === 0) return;

    fc.features.forEach(feature => {
      feature.properties.uid = DataUtils.uuid();
    });
  }

  /**
   * 获取唯一要素集合
   * @param {Array} features -要素集合
   * @param {String} name -属性名称
   *
   * @returns {Array}
   */
  static getUniqueFeatures(features, name) {
    let existingFeatureKeys = {};
    // Because features come from tiled vector data, feature geometries may be split
    // or duplicated across tile boundaries and, as a result, features may appear
    // multiple times in query results.
    let uniqueFeatures = features.filter(function (feature) {
      if (existingFeatureKeys[feature.properties[name]]) {
        return false;
      } else {
        existingFeatureKeys[feature.properties[name]] = true;
        return true;
      }
    });

    return uniqueFeatures;
  }

  /**
   * 获取唯一对象集合
   * @param {Array} items -对象集合
   * @param {String} name -属性名称
   *
   * @returns {Array}
   */
  static getUniqueObjects(items, name) {
    let existingItemKeys = {};

    let uniqueItems = items.filter(function (item) {
      if (existingItemKeys[item[name]]) {
        return false;
      } else {
        existingItemKeys[item[name]] = true;
        return true;
      }
    });

    return uniqueItems;
  }

}

