import { Geometry } from "./Geometry";
import { Image } from "./Image";
import { PrintObject } from "./PrintObject";
import { Number } from "../dataType/Number";
import { String } from "../dataType/String";
import { Array } from "../dataType/Array";
import { Boolean } from "../dataType/Boolean";
import { FeatureCollection } from "./FeatureCollection";

import { Reducer } from "./Reducer";
import { Filter } from "./Filter";
import { MosaicData } from "./MosaicData";
import { Dictionary } from "./Dictionary";
import { AstHelper } from "@gvol-org/geovis-brain-core";
import { Collection } from "../internal/Collection";
import { Http } from "../Http";
import { List } from "../dataType/List";
import { Util } from "../common/util";
// import { AstHelper } from "../common/AstHelper";
/**
 *  gve
 * @class gve.ImageCollection
 * @since gve
 */
export class ImageCollection extends PrintObject {
  /**
   * 构造影像集合
   * @hideconstructor
   * @param {Image|Array<Object>|String} [args] 构造函数参数
   * @returns gve.ImageCollection
   */
  constructor(args?: Image | Array<Object> | String) {
    super();
    if (!(this instanceof ImageCollection)) {
      return new ImageCollection(args);
    }
    this.args = args;
  }

  args: any;

  type: string = "ImageCollection";

  elements: Array<Image>;

  /**
   * 云盘检索数据集,按日期过滤
   * @param {string} start 开始日期。格式为'yyyy-mm-dd'
   * @param {string} end 结束日期。格式为'yyyy-mm-dd'
   * @returns ImageCollection
   */
  filterDate(start: string, end: string) {
    //校验日期格式是否符合要求
    if(!Util.validateDate(start)){
      throw new Error(`日期输入错误:${start}`);
    }
    if(!Util.validateDate(end)){
      throw new Error(`日期输入错误:${end}`);
    }
    return new ImageCollection();
  }
  /**
   * 返回与输入字符串定义的点相交的图像
   * @param {String} point 用于筛选的点的字符串表示形式。格式为'[经度,纬度]'
   * @returns ImageCollection
   */
  filterBoundsPoint(point: string) {
    return new ImageCollection();
  }
  /**
   * 过滤ImageCollection以只包含与给定直线相交的图像
   * @param {String} line 用于筛选的线的点集。格式为'[[经度,纬度],[经度,纬度],...]'
   * @returns ImageCollection
   */
  filterBoundsLine(line: string) {
    return new ImageCollection();
  }

  /**
   * 根据波段名称从影像集合中选择波段,返回一个影像集合对象
   * @param { string | string[]} bands 指定要选择的波段
   * @param { string[] } [newBandIds] 波段重命名, 可选参数
   * @returns ImageCollection
   */
  select(bands?: string | string[], newBandIds?:string[]) {
    return new ImageCollection();
  }

  /**
   * 针对ImageCollection中的每个Image进行循环计算
   * @param {Function} algorithm 将应用于集合中的每个图像的算法
   * @returns Collection
   */
  map(algorithm: Function) {
    var im = new Image() as any;
    //处理表达式
    // im.expressions = "image";
    im.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, im);
    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);

    // console.log("imagecollection map===", res)

    var collection = new ImageCollection();
    // (collection as any).expressions = "function (image){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;
    
  }

  /**
   * 将影像集合融合成为一张影像Image,返回最后一个有像素的Image对象
   * @param {string} [method] 选择影像镶嵌的方法,可选,"median|mean|max|min",默认值median
   * @param {number} [scale] 分辨率,可选,默认300
   * @returns Image
   */
  mosaic(method?: string, scale?: number) {
    if(scale){
      Http.scale = scale.toString();
    }
    return new Image();
  }

  /**
   * 按照指定的矢量边界裁剪影像。除了未被几何覆盖的数据被掩盖之外,裁剪前后的影像波段完全对应。裁剪后影像保留裁剪前的元数据。
   * @param {Geometry} imc Geometry实例
   * @returns ImageCollection
   */
  clip(imc: Geometry) {

    return new ImageCollection();
  }

  private value() {
    return new ImageCollection();
  }

  /**
   * 获取影像的列表
   * @param {Number} [count] 可选参数,要获取的元素数
   * @param {Number} [start] 可选参数,开始的元素数
   * @returns Array<ImageCollection>
   */
  toList(count?: number, start?: number) {
    return new ImageCollection();
  }

  /**
   * 返回影像集合的首位影像
   * @returns Image
   */
  first() {
    return new Image();
  }

  /**
   * 返回影像集合的大小
   * @returns Number
   */
  size() {

    return new Number();
  }

  /**
   * 根据给定字段排序
   * @param {String} property 字段名
   * @param {Boolean} [ascending] 可选参数,boolean(true为升序,false为降序,不填默认为true)
   * @returns ImageCollection
   */
  sort(property: string, ascending?: boolean) {
    return new ImageCollection();
  }

  /**
   * 调试输出。 调用一个函数,将该对象作为第一个参数传递,并返回其本身
   * @param {Function} func 要调用的函数
   * @param {Array<Object>} var_args 任何要传递给函数的额外参数
   * @returns {ImageCollection} ImageCollection
   */
  aside(func: Function, ...var_args: Object[]) {
    func.call(this, this, ...var_args);
    return this;
    // console.log("调用aside函数", ...var_args)
    // func(this, ...var_args);
    // return new ImageCollection();
  }

  /**
   * 将两个图像集合合并为一个,结果将包含这两个集合中的所有图像
   * @param {ImageCollection} collection2 要合并的第二个集合
   * @returns ImageCollection
   */
  merge(collection2: ImageCollection) {
    return new ImageCollection();
  }

  /**
   * 循环执行并返回结果
   * @param {Function} func 循环执行的函数
   */
  iterate(func: Function) {
    var im = new Image() as any;
    // im.expressions = "image";
    im.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 = func.call(this, im);   
    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 ImageCollection();
    // (collection as any).expressions = "function (image){return " + resExp + "}";
    if(res.reference){
      collection["reference"] = res.reference;
      collection["chain"] = res.chain;
      collection["order"] = res.order;
      collection["orgObjectKey"] = orgObjectKey;
      func["reference"] = res.reference;
    }
    return collection;
  }

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

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

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

  /**
   * 获取ImageCollection中指定属性列表值,返回列表第一个值。
   * @param {String} param 属性名称
   * @returns Dictionary
   */
  aggregate_first(param: string) {
    return new Dictionary();
  }

  /**
   * 获取ImageCollection所选属性的柱状图,返回json
   * @param {String} param 属性名称
   * @returns Dictionary
   */
  aggregate_histogram(param: string) {
    return new Dictionary();
  }

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

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

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

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

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

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

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

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

  /**
   * 获取ImageCollection所选属性的统计信息,返回json
   * @param {String} param 属性名称
   * @returns Dictionary
   */
  aggregate_stats(param: string) {
    return new Dictionary();
  }

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

  /**
   * 云盘检索数据集,按云量过滤
   * @param {String} operator 关系运算符:lt:"<",le:"<=",eq:"=",ge:">=",gt:">"
   * @param {Number} count 云量
   * @returns ImageCollection
   */
  filterCloud(operator: string, count: number) {
    return new ImageCollection();
  }

  /**
   * 云盘检索数据集,按边界值过滤
   * @param {Geometry|FeatureCollection} geometry 边界Geometry
   * @returns ImageCollection
   */
  filterBounds(geometry: Geometry|FeatureCollection) {
    return new ImageCollection();
  }

  /**
   * 云盘检索数据集,按ECQL过滤
   * @param {String} ecql ecql语句,参考链接 https://www.osgeo.cn/geoserver-user-manual/filter/ecql_reference.html
   * @returns ImageCollection
   */
  filterECQL(ecql: string) {
    return new ImageCollection();
  }

  /**
   *  批量计算全国的ndvi.
   *  @returns ImageCollection
   */
  ndvi() {
    return new ImageCollection();
  }

  /**
   * 求取不同image相同波段像素的最大值
   * @returns Image
   */
  max() {
    return new Image();
  }

  /**
   * 求取不同image相同波段像素的最小值
   * @returns Image
   */
  min() {
    return new Image();
  }

  /**
   * 求取不同image相同波段像素的均值
   * @returns Image
   */
  mean() {
    return new Image();
  }

  /**
   * 求取不同image相同波段像素的中值
   * @returns Image
   */
  median() {
    return new Image();
  }

  /**
   * 求取不同image相同波段像素的乘积
   * @returns Image
   */
  product() {
    return new Image();
  }

  /**
   * 求取不同image相同波段像素的和
   * @returns Image
   */
  sum() {
    return new Image();
  }

  // /**
  //  * 影像集合快速镶嵌
  //  * @param {string} [method] 支持算法 median|mean|max|min",默认值median
  //  * @param {Array<string>} [bandNames] 波段名数组,例如["B4", "B3", "B2"],可选参数,默认用第一个image的首个波段, 比如 第一个image的首个波段是B2,那quickMosaic就是用所有image的B2波段合成
  //  * @param {number} [min] 最小层级,默认5,可选参数 
  //  * @param {number} [max]  最大层级,默认13,可选参数 
  //  * @param {any} [type] 支持json|sqlite,默认sqlite,可选参数 
  //  * @returns MosaicData
  //  */
  // quickMosaic(method:string='median', bandNames?: Array<string>|string[], min?: number, max?: number, type?: any) {
  //   return new MosaicData();
  // }


  // /**
  //  *  波段合成
  //  *  @param {String} band 需要合成的波段值
  //  *  @return ImageCollection
  //  */
  // compositeBands(band: string) {
  //   return new ImageCollection();
  // }
  /**
   * 获取影像的云量和日期
   * @returns object
   */
  getCloudAndDate(callback: Function) {
    console.log("getCloudAndDate");
    if (Http.promiseCloudUrl == "") {
      console.log("sdk pyWeb的Url传入错误");
      return;
    }
    fetch(Http.promiseCloudUrl + "?path=" + this.args, {
      signal: Http.signal,
      headers: {
        'token': Http.userToken,
        "enableCache": Http.enableCache
    },
    }).then(
      response => response.json()).then(
        response => {
          console.log("getCloudAndDate response", response);
          callback(response);
        }).catch(error => {
          if (error.name === 'AbortError') {
            console.log('请求已中止');
          } else {
            console.error('请求失败', error);
          }
          return;
        });
    //    return {cloud:[99.99, 100, 66.3, 100, 99.99, 96.81, 99.97, 98.97, 95.28, 4.12, 0.64, 82.72, 99.96, 69.81, 0.32, 22.56, 0.83, 1.17, 36.28, 0.59, 89.12, 0.04, 0.19],date:[20220106, 20220122, 20220207, 20220428, 20220514, 20220717, 20221005, 20221122, 20221208, 20220223, 20220311, 20220327, 20220412, 20220530, 20220615, 20220701, 20220802, 20220818, 20220903, 20220919, 20221021, 20221106, 20221224]};
  }

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

  /**
   *  对ImageCollection进行分页
   *  @param {number} page 页数
   *  @param {number} count 每页数据数
   *  @return ImageCollection
   */
  page(page: number, count: number) {
    return new ImageCollection();
  }

  /**
   *  将一个统计器应用到影像集合中的所有影像
   *  @param {Reducer} reducer Reducer实例
   *  @return Image
   */
  reduce(reducer: Reducer) {
    return new Image();
  }

  /**
   *  云盘检索数据集条件过滤
   *  @param {string} filter Filter函数的返回值
   *  @return ImageCollection
   */
  filter(filter: Filter) {
    return new ImageCollection();
  }

  /**
   *  执行超分函数
   *  @param {number} scale 分辨率
   *  @param {boolean} asyncFlag 是否异步计算
   *  @param {number} [batch]  批处理量,批量处理每次处理的数量,可选参数,默认20
   *  @return ImageCollection
   */
  grid_super_resolution(scale: number, asyncFlag: boolean, batch?: number) {
    if(scale){
      Http.scale = scale.toString();
    }
    return new ImageCollection();
  }

  /**
   * 将某一个网格转成一个ImageCollection对象
   * @param {Array<any>} wkt wkt格式的Geometry
   * @param {string} [format] 可选参数,格式
   * @param {string} [dataset] 可选参数,数据集名字,默认值是'base08'
   * @param {number} [buffer] 可选参数,外扩,单位是度,默认值是0
   * @param {string} [gpu_path] 可选参数,生成的vrt或者tif路径是否保存到gpudata路径,默认为false
   * @returns ImageCollection
   */
  fromGrid(wkt: Array<any>, format?: string, dataset?: string, buffer?: number, gpu_path?: boolean) {
    return new ImageCollection();
  }

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

  /**
   * 基于自然语言理解来计算影像集合的ndvi
   * @param {string} text_target 自然语言指令
   * @returns ImageCollection
   */
  NLUCalculator(text_target: string) {
    return new ImageCollection();
  }

  /**
   * 设置ImageCollection下的属性信息
   * @param {object | array} var_args var_args为字典或键值对
   * @returns ImageCollection
   */
  set(...var_args: any[]) {
    return new ImageCollection();
  }

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

  /**
   * 按月优选函数
   * @param {number} [supplement] supplement=1,代表补数据,supplement=0,代表不补充数据,默认为0
   * @returns ImageCollection
   */
  monthSelected(supplement: number = 0){
    return new ImageCollection();
  }

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

  /**
   * 返回给定影像的集合
   * @param {List|Image[]} images 集合中包含的影像
   * @returns ImageCollection
   * @tutorial gve.ImageCollection
   */
  static fromImages(images: List<any>|Image[]) {
    return new ImageCollection();
  }

  /**
   * 组合集合中所有影像,使用质量波段作为每个像素的排序函数
   * @param {string} qualityBand 集合中质量波段名称
   * @return Image
   */
  qualityMosaic(qualityBand: string) {
    return new Image();
  }

  /**
   * 将影像集合中所有影像的波段转换成单张多波段影像
   * @returns Image
   */
  toBands() {
    return new Image();
  }

//  /**
//   * 生成趋势
//   * @param {String} lineType 趋势方法,LINEAR|POLYNOMIAL|HARMONIC|MANN-KENDALL|SEASONAL-KENDALL 五个之一
//   * @param {Boolean} [ignoreNodata] 忽略nodata值, 默认为false
//   * @param {Boolean} [RMSE] 均方根误差, 默认为false,lineType为LINEAR|POLYNOMIAL|HARMONIC 有此参数
//   * @param {Boolean} [slopePValue] 斜率, 默认为false, LINEAR|HARMONIC 有此参数
//   * @param {Boolean} [RSquared] 方差, 默认false LINEAR|POLYNOMIAL|HARMONIC 有此参数
//   * @param {Number} [frequency] 频率,默认为1,POLYNOMIAL|HARMONIC 有此参数
//   * @param {String} [cycleUnit] 周期, 默认为YEARS  HARMONIC 有此参数
//   * @param {Number} [cycleLength] 周长,默认为1,HARMONIC 有此参数
//   * @returns Image
//   */
//   generateTrendRaster(lineType:"LINEAR"|"POLYNOMIAL"|"HARMONIC"|"MANN-KENDALL"|"SEASONAL-KENDALL",ignoreNodata?:boolean, RMSE?:boolean, slopePValue?:boolean,RSquared?:boolean,frequency?:number,cycleUnit?:string,cycleLength?:number){
//     return new Image();
//   }
  /**
   * 同一位置影像集合线性趋势分析
   * @param {Boolean} [ignoreNodata] 忽略nodata值, 默认为false
   * @param {Boolean} [RMSE] 均方根误差, 默认为false
   * @param {Boolean} [slopePValue] 斜率, 默认为false
   * @param {Boolean} [RSquared] 方差, 默认false
   * @returns Image
   */
  LinearGenerateTrend(ignoreNodata:boolean=false, RMSE:boolean=false, slopePValue:boolean=false,RSquared:boolean=false) {
    return new Image();
  }

    /**
   * 生成趋势
   * @param {Boolean} [ignoreNodata] 忽略nodata值, 默认为false
   * @param {Boolean} [RMSE] 均方根误差, 默认为false
   * @param {Boolean} [RSquared] 方差, 默认false
   * @param {Number} [frequency] 频率,默认为1
   * @returns Image
   */
    PolynomialGenerateTrend(ignoreNodata:boolean=false, RMSE:boolean=false, RSquared:boolean=false,frequency:number=1) {
      return new Image();
  }
  /**
  * 生成趋势
  * @param {Boolean} [ignoreNodata] 忽略nodata值, 默认为false
  * @param {Boolean} [RMSE] 均方根误差, 默认为false
  * @param {Boolean} [slopePValue] 斜率, 默认为false
  * @param {Boolean} [RSquared] 方差, 默认false 
  * @param {Number} [frequency] 频率,默认为1
  * @param {String} [cycleUnit] 周期, 默认为YEARS
  * @param {Number} [cycleLength] 周长,默认为1
  * @returns Image
  */
  HarmonicGenerateTrend(ignoreNodata:boolean=false, RMSE:boolean=false, slopePValue:boolean=false,RSquared:boolean=false,frequency:number=1,cycleUnit:string='YEARS',cycleLength:number=1){
    return new Image();
  }

  /**
   * 生成趋势
   * @param {Boolean} [ignoreNodata] 忽略nodata值, 默认为false
   * @returns Image
   */
  MannKendallGenerateTrend(ignoreNodata:boolean=false){
    return new Image();
  }
  /**
   * 生成趋势
   * @param {Boolean} [ignoreNodata] 忽略nodata值, 默认为false
   * @returns Image
   */
  SeasonalKendallGenerateTrend(ignoreNodata:boolean=false){
    return new Image();
  }


  //研发自用,无需在文档中显示
  static stac_search(collections?:any,ids?:any, bbox?:any,datetime?:any,intersects?:any,limit?:any,max_items?:any,conf?:any,query?:any,sortby?:any,fiellds?:any,filter?:any,filter_crs?:any,filter_lang?:any,token?:any){
    return new ImageCollection();
  }
  
}