import VerifyUtils from "./VerifyUtils";

/**
 * GeoJSON定义工具类
 */
const GeoJsonUtils = {
  /**
   * 获取空要素集
   * 
   * @returns {Object} GeoJson根对象
   */
  getEmptyFC() {
    return {
      type: 'FeatureCollection',
      features: []
    };
  },
  
  /**
   * 获取要素集
   * @param {Array} features -要素列表
   * 
   * @returns {Object} GeoJson根对象
   */
  getFC(features) {
    const fc = this.getEmptyFC();

    if (VerifyUtils.isArray(features) && features.length > 0 && 
        VerifyUtils.isFeature(features[0])) {
      fc.features = features;
    }

    return fc;
  },

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

  /**
   * 获取要素
   * @param {Object} geometry -几何图形
   * @param {Object} properties -属性
   * 
   * @returns {Object} GeoJson要素对象
   */
  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点要素对象
   */
  getPointFeature(lonLat, props = null) {
    let feature = this.getEmptyFeature('Point');
    // 几何图形
    if (lonLat && lonLat.length > 1) {
      feature.geometry.coordinates = lonLat;
    }
    // 属性
    if (props) {
      feature.properties = props;
    }

    return feature;
  },

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

    return feature;
  },

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

    return feature;
  },

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

    return feature;
  },

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

    return feature;
  },

  /**
   * 获取多多边形要素
   * @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多多边形要素对象
   */
  getMultiPolygonFeature(polygons, props = null) {
    let feature = this.getEmptyFeature('MultiPolygon');
    // 几何图形
    if (polygons && polygons.length > 0) {
      feature.geometry.coordinates = polygons;
    }
    // 属性
    if (props) {
      feature.properties = props;
    }

    return feature;
  },
  
  /**
   * 获取Geometry类型
   * @param {Object} feature -要素
   * 
   * @return {String}
   */
  getGeometryType(feature) {
    return feature.geometry.type;
  },

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

    let newFeature = this.getEmptyFeature(feature.geometry.type);
    newFeature.id = feature.id;
    
    // 拷贝坐标数组
    let [...coordinates] = feature.geometry.coordinates;
    newFeature.geometry.coordinates = coordinates;
    
    for (let key in feature.properties) {
      newFeature.properties[key] = feature.properties[key];
    }

    return newFeature;
  },

  /**
   * 获取唯一要素集合
   * @param {Array} features -要素集合
   * @param {String} name -属性名称
   * 
   * @returns {Array} 唯一要素集合
   */
  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|Object} data -JSON集合
   * 
   * @returns {FeatureCollection}
   */
  array2PointFC(data) {
    const fc = this.getEmptyFC();

    if (VerifyUtils.isArray(data)) {
      /*
      fc.features = data.map((pt) => {
        let lon = Number(pt.lng || pt.longitude || pt.lon);
        let lat = Number(pt.lat || pt.latitude);

        // 获取点要素
        return this.getPointFeature([lon, lat], pt);
      });
      */
      data.forEach((pt) => {
        let lon = pt.lng || pt.longitude || pt.lon || pt.Longitude;
        let lat = pt.lat || pt.latitude || pt.Latitude;
        
        if (lon && lat && lon !== 'null' && lat !== 'null') {
          // 添加点要素
          const feature = this.getPointFeature([Number(lon), Number(lat)], pt);
          fc.features.push(feature);
        }
      });
    }

    return fc;
  },

  /**
   * 对象转点要素
   * @param {Object} data -点位对象
   * 
   * @returns {Feature}
   */
  object2PointFeature(data) {
    let lon = data.lng || data.longitude || data.lon;
    let lat = data.lat || data.latitude;

    if (lon && lat && lon !== 'null' && lat !== 'null') {
      return this.getPointFeature([Number(lon), Number(lat)], data);
    }

    return null;
  },

  /**
   * 点要素转多边形要素
   * @param {Object|Array} data -GeoJSON要素/经纬度
   * 
   * @returns {Object}
   */
  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);
  }
}

export default GeoJsonUtils;