import { String } from "../dataType/String";
import { PrintObject } from "./PrintObject";
import { Array } from "../dataType/Array";
import { Number } from "../dataType/Number";
import { Boolean } from "../dataType/Boolean";
import { Geometry } from "./Geometry";
import { Dictionary } from "./Dictionary";
import { Feature } from "./Feature";
import { AstHelper } from "@gvol-org/geovis-brain-core";
import { List } from "../dataType/List";
import { Filter } from "./Filter";
import { Classifier } from "./Classifier";
import { ConfusionMatrix } from "./ConfusionMatrix";
import { Collection } from "../internal/Collection";
import { Http } from "../Http";
import { Util } from "../common/util";
import { File } from "./File";
import { Reducer } from "./Reducer";
import { Image } from "./Image";
import { Clusterer } from "./Clusterer";
/**
 *  gve
 * @class gve.FeatureCollection
 * @since gve
 */
export class FeatureCollection extends PrintObject {
  /**
   * 通过矢量数据构造Feature集合
   * @hideconstructor
   * @param {any} [args] 矢量数据路径或Geometry、Feature实例等
   * @param {string} [condition] 过滤条件语句
   * @returns gve.FeatureCollection
   */
  constructor(args?: any, condition?: string) {
    super();
    this.type = "FeatureCollection";
    if (!(this instanceof FeatureCollection)) {
      return new FeatureCollection(args, condition);
    }
  }

  type: string = "FeatureCollection";

  /**
   * 获取数据信息,返回json
   * @returns FeatureCollection
   */
  getInfo() {
    if (this.type != "FeatureCollection") {
      return;
    }
    return new FeatureCollection();
  }

  /**
   * 加载数据,按区域搜索。参数为中国范围省市县(区)全拼,按位置传,至少传一个
   * @param {String} province 省
   * @param {String} [city] 市
   * @param {String} [district] 县(区)
   * @returns FeatureCollection
   */
  adm_search(province: string, city?: string, district?: string) {
    return new FeatureCollection();
  }

  /**
   * 获取FeatureCollection所选属性的所有值列表
   * @param {String} property 属性名
   * @returns List
   */
  aggregate_array(property: string) {
    return new List();
  }

  /**
   * 获取FeatureCollection所选属性的总个数
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_count(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的唯一值总个数
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_count_distinct(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的第一个值
   * @param {String} property 属性名
   * @returns 
   */
  aggregate_first(property: string) {
    return new Dictionary();
  }

  /**
   * 获取FeatureCollection所选属性的柱状图
   * @param {String} property 属性名
   * @returns Dictionary
   */
  aggregate_histogram(property: string) {
    return new Dictionary();
  }

  /**
   * 获取FeatureCollection所选属性的最大值
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_max(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的平均数
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_mean(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的最小值
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_min(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的乘积
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_product(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的均方差
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_sample_sd(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的方差
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_sample_var(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的总均方差
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_total_sd(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的总方差
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_total_var(property: string) {
    return new Number();
  }

  /**
   * 获取FeatureCollection所选属性的统计信息
   * @param {String} property 属性名
   * @returns Dictionary
   */
  aggregate_stats(property: string) {
    return new Dictionary();
  }

  /**
   * 获取FeatureCollection所选属性的总和
   * @param {String} property 属性名
   * @returns Number
   */
  aggregate_sum(property: string) {
    return new Number();
  }

  /**
   * @description 返回FeatureCollection的首个Feature对象
   * @returns Feature
   */
  first() {
    return new Feature();
  }

  /**
   * @description 返回FeatureCollection的几何图形信息,几何信息以Json形式表示
   * @returns Geometry
   */
  geometry() {
    return new Geometry();
  }

  /**
   *  返回集合中指定数量的要素的集合
   *  @param {number} count 要素个数
   *  @return FeatureCollection
   */
  limit(count: number) {
    return new FeatureCollection();
  }

  /**
   * 转FeatureCollection为矢量瓦片服务
   * @return FeatureCollection
   */
  localServeAsVectorTile() {
    return new FeatureCollection();
  }

  /**
   * 合并FeatureCollection
   * @return FeatureCollection
   */
  unary_union() {
    return new FeatureCollection();
  }

  /**
   * 根据数据的投影、分辨率、计算覆盖geometry的grid
   * @param {Object|string} tif_proj 待转换的投影坐标, object或者字符串
   * @param {number} [scale] 待转换的分辨率,如果tif_proj输入的是str类型的,必须输入这个分辨率,如果tif_proj输入dict,这个参数可以不输入
   * @returns FeatureCollection
   */
  covering_grid(tif_proj: Object | string, scale?: number) {
    if(scale){
      Http.scale = scale.toString();
    }
    return new FeatureCollection();
  }

  /**
   * NLU行政区划检索
   * @param {string} keyword 检索字段
   * @returns FeatureCollection
   */
  fromNLU(keyword: string) {
    return new FeatureCollection();
  }

  /**
   * 网格数据生成featureCollection数据类型
   * @param {Array<any>} wkt wkt格式的Geometry
   * @returns FeatureCollection
   */
  wktToFeatureCollection(wkt: Array<any>) {
    return new FeatureCollection();
  }

  /**
   * 针对FeatureCollection中的每个Feature进行循环计算
   * @param {Function} algorithm 将应用于集合中的每个图像的算法
   * @returns Collection
   */
  map(algorithm: Function) {
    var fe = new Feature() as any;
    // fe.expressions = "feature";
    fe.tag = "orgObject";

    //先存一下当前的publicChain和publicIndex,等执行完恢复
    let oldChain = [...AstHelper.publicChain];
    let oldIndex = AstHelper.publicIndex;
    let oldBlockNo = AstHelper.blockNo;
    //将当前层级之前的调用链存放在allChain的最后,当执行完当前层级后删掉
    // let publicChainLength = AstHelper.publicChain.length;
    // AstHelper.allChain.push(...AstHelper.publicChain);
    let mapChain: any[] = [];
    let mapIndex: number = 0;
    AstHelper.publicChain = mapChain;
    AstHelper.publicIndex = mapIndex;
    AstHelper.blockNo = AstHelper.mapBlockNo + 1;
    AstHelper.mapBlockNo ++;
    let orgObjectKey = "".padStart(AstHelper.blockNo, '$') + "orgObject";

    var res = algorithm.call(this, fe);   
    res["chain"] = AstHelper.relativeChain(res.order);
    AstHelper.publicChain = oldChain;
    AstHelper.publicIndex = oldIndex;
    AstHelper.blockNo = oldBlockNo;
    
    // AstHelper.allChain = AstHelper.allChain.slice(0, AstHelper.allChain.length - publicChainLength);

    var resExp = AstHelper.stringify(res)
    
    var collection = new FeatureCollection();
    // (collection as any).expressions = "function (feature){return " + resExp + "}";
    if(res.reference){
      collection["reference"] = res.reference;
      collection["chain"] = res.chain;
      collection["order"] = res.order;
      collection["orgObjectKey"] = orgObjectKey;
      algorithm["reference"] = res.reference;
    }
    return collection;
  }

  /**
   * 将确定性伪随机数列添加到集合中
   * @param {string} [columnName] 要添加的列的名称,默认值'random'
   * @param {number} [seed] 生成随机数时使用的种子,默认值 0
   * @param {string} [distribution] 产生的随机数的分布类型,默认值'uniform'
   * @returns FeatureCollection
   */
  randomColumn(columnName: string='random', seed: number=0, distribution: string='uniform') {
    return new FeatureCollection();
  }

  /**
   * 通过比较集合的两列:一列包含实际值,另一列包含预测值,为集合计算2D误差矩阵
   * @param {any} actual 实际值
   * @param {List<number>|string} predicted 预测值
   * @param {List<number>|string} orderList 期望值列表
   * @returns ConfusionMatrix
   */
  errorMatrix(actual: any, predicted: number[]|List<number>|string, orderList: number[]|List<number>|string = null) {
    return new ConfusionMatrix();
  }

  /**
   * 对featureColelction进行过滤
   * @param {Filter|string} filter 过滤条件
   * @returns FeatureCollection
   */
  filter(filter: Filter|string) {
    return new FeatureCollection();
  }     

  /**
   * 对集合中的每个feature进行分类
   * @param {Classifier} classifier 使用的分类器
   * @returns FeatureCollection
   */
  classify(classifier: Classifier) {
    return new FeatureCollection();
  } 

  /**
   * 按日期过滤矢量集合
   * @param {Date|number|string} start 开始日期
   * @param {Date|number|string} [end] 结束日期,可选参数
   * @returns FeatureCollection
   */
  filterDate(start: Date|number|string, end?: Date|number|string) {
    //校验日期格式是否符合要求
    if(typeof start == 'string' && !Util.validateDate(start)){
      throw new Error(`日期输入错误:${start}`);
    }
    if(typeof end == 'string' && !Util.validateDate(end)){
      throw new Error(`日期输入错误:${end}`);
    }
    return new FeatureCollection();
  }

  /**
   * 按边界值过滤矢量集合
   * @param {Geometry|FeatureCollection} geometry 边界Geometry
   * @returns FeatureCollection
   */
  filterBounds(geometry: Geometry|FeatureCollection) {
    return new FeatureCollection();
  }

  /**
   * 获得FeatureCollection对象中指定编号的Feature对象
   * @param {number} index 元素索引
   * @returns Feature
   */
  getAt(index: number) {
    return new Feature();
  }

  /**
   * 根据属性名获得FeatureCollection下对应属性值信息
   * @param {string} property 属性名
   * @returns any
   */
  get(property: string) {
    return new PrintObject();
  }

  /**
   * 设置FeatureCollection下的属性信息
   * @param {string} key 属性名称
   * @param {any} value 属性值
   * @returns FeatureCollection
   */
  set(key: string, value: any) {
    return new FeatureCollection();
  }

  /**
   * 返回矢量集合的大小
   * @returns Number
   */
  size() {
    return new Number();
  }

  /**
   * 获得FeatureCollection下的属性名
   * @returns List
   */
  propertyNames() {
    return new List();
  }

  /**
   * 合并两个FeatureCollection
   * @param {FeatureCollection} collection2 FeatureCollection实例
   * @returns FeatureCollection
   */
  merge(collection2: FeatureCollection) {
    return new FeatureCollection();
  }

  /**
   * 三维模型文件生成
   * @param {string} [format] 可选参数,文件格式类型,默认值'fbx'
   * @returns File
   */
  to3DModel(format?: string) {
    return new File();
  }

  /**
   * 在给定区域和属性相交区域内使用reducer创建影像
   * @param {List|any[]} properties 选定的属性
   * @param {Reducer} reducer 应用的Reducer实例
   * @returns Image
   */
  reduceToImage(properties: List<any>|any[], reducer: Reducer) {
    return new Image();
  }
  /**
   * 进行聚类
   * @param {Clusterer} clusterer 使用的聚类
   * @param {String} [outputName] 需要增加的输出属性
   * @returns FeatureCollection
   */
  cluster(clusterer:Clusterer, outputName?:string){
    return new FeatureCollection();
  }

  /**
   * 复制属性
   * @param {List|any[]} source FeatureCollection类型
   * @param {List|any[]} [properties] 复制的属性列表
   * @param {List|any[]} [exclude] 排除的属性列表
   * @returns FeatureCollection
   */
  copyProperties(source:List<any>|any[], properties?:List<any>|any[], exclude?:List<any>|any[]){
    return new FeatureCollection();
  }

  /**
   * 移除重复属性
   * @param {List<any>|any[]|String} properties 属性
   * @returns FeatureCollection
   */
  distinct(properties: List<any>|any[]|string){
    return new FeatureCollection();
  }

  /**
   * 几何特征集合拉平
   * @returns FeatureCollection
   */
  flatten(){
    return new FeatureCollection();
  }

  /**
   * 从几何特征中提取Array属性
   * @param {String} property 待获取的Array属性
   * @returns Array
   */
  getArray(property:string){
    return new Array();
  }
  /**
   * 从几何特征中提取Number属性
   * @param {String} property 待获取的Number属性
   * @returns Number
   */
  getNumber(property:string){
    return new Number();
  }

  /**
   * 从几何特征中提取String属性
   * @param {String} property 待获取的String属性
   * @returns String
   */
  getString(property:string){
    return new String();
  }
  /**
   * 根据特定的属性对集合进行排序
   * @param {String} property 待获取的String属性
   * @param {Boolean} [ascending] 按指定的升序或者降序排序
   * @returns FeatureCollection
   */
  sort(property:string, ascending?:boolean){
    return new FeatureCollection();
  }

  /**
   * 提取特定属性构造字典
   * @param {List|any[]} properties 属性列表
   * @returns Dictionary
   */
  toDictionary(properties:List<any>|any[]){
    return new Dictionary();
  }
  /**
   * 提取特定属性构造列表
   * @param {String} count 取到的元素个数
   * @param {String} [offset] 从开始位置舍弃的元素
   * @returns List
   */
  toList(count:number, offset?:number){
    return new List();
  }
  /**
   * 在给定的几何形状中生成均匀随机的点
   * @param {Geometry} geometry 给定的几何形状
   * @param {Number} [points] 随机点数
   * @returns FeatureCollection
   * @tutorial gve.FeatureCollection
   */
  static randomPoints(geometry:Geometry, points?:number|Number){
    return new FeatureCollection();
  }

}