import { Widget } from "./Widget";
import { Http } from "../Http";
import { FeatureCollection } from "../models/FeatureCollection";
import { MosaicData } from "../models/MosaicData";
import { Geometry } from "../models/Geometry";
import { Feature } from "../models/Feature";
import { Image } from "../models/Image";
import { Guid } from "@gvol-org/geovis-brain-core";
import { DrawingTools } from "./DrawingTools";
import * as turf from '@turf/turf';
import { Subject } from "rxjs";
import Compare from "mapbox-gl-compare";
import { ui } from "./ui";
import mapboxgl from "mapbox-gl";
import { AddLayer } from "../models/AddLayer";
import { MapUtil } from "@gvol-org/geovis-brain-core";
import { Mvt } from "../models/Mvt";
import { BatchProcessing } from "../batchProcessingsdk/BatchProcessing";
/**
 * @class ui.Map
 * @since ui
 */
export class Map extends Widget {
  addLayerParams: any = [];//保存addLayer方法的参数
  addUIParams: any = [];//保存addUI方法的参数
  removeUIParams: any = [];//保存removeUI方法的参数
  removeLayerParams: any = [];//保存removeLayer方法的参数
  flytoParams: any = [];//保存flyto方法的参数
  additionLayer: any;//保存卷帘函数额外需要添加的图层
  controlVisibilityParams: any = [];
  setCenterParams: object;
  setZoomParam: number;
  map: any;//mapbox对象
  id: string;
  onClick: Function;
  layerList: any = [];//addLayer的图层列表
  scaleDic: any = [156543.03, 78271.52, 39135.76, 19567.88, 9783.94, 4891.97, 2445.98, 1222.99, 611.50, 305.75, 152.87, 76.44, 38.22, 19.11, 9.55, 4.78, 2.39, 1.19, 0.60, 0.30];
  mapUI: HTMLElement;
  drawTools: DrawingTools;
  toolBtnLocat: any; //设置地图上的按钮的位置
  featuresLayerInfo: Array<any> = [];
  loadTileCount: number = 0;
  requestTileTotal: number = 0;
  loadTilePercent: number = 0;
  showTileLoadProgress: boolean = false;

  /**
   * @hideconstructor
  * @param {object} [center] 地图默认中心点
  * @param {Function} [onClick]  地图点击事件
  * @param {object} [style] 地图样式
   * @return ui.Map
   */
  constructor(
    center?: object,
    onClick?: Function,
    style?: object
  ) {

    let mapContainer = document.createElement("div");
    mapContainer.style.flex = '1';
    mapContainer.style.height = '100%';
    mapContainer.style.width = '100%';
    mapContainer.style.position = 'relative';
    mapContainer.style.display = 'block';
    mapContainer.style.minHeight = '200px';
    mapContainer.style.minWidth = '200px';

    let mapUI = document.createElement("div");
    mapUI.classList.add("map-ui-div");
    mapContainer.appendChild(mapUI);
    super(mapContainer, style);
    if (!(this instanceof Map)) {
      return new Map(center, onClick, style);
    }
    this.mapUI = mapUI;
    if (center) {
      this.setCenterParams = center;
    }
    if (onClick) {
      this.onClick = onClick;
    }
    this.id = Guid.newGuid();
    Http.generateComponentSubject$.next({
      name: 'Map',
      component: this,
      data: {
        id: this.id,
        map: this.map
      }
    });
    this.toolBtnLocat = {
      baseMapLocat: "bottom-right",
      layerListLocat: "top-right",
      navigationCtrlLocat: "bottom",
      FullscreenCtrlLocat: "bottom-right"
    }
  }
  setSubject(sub: any) {
    this.stateChanged$ = sub;
  }

  public stateChanged$ = new Subject()
  //用于监听setptions的调用
  setOptionsSubject(sub: any){
    this.changeBaseMap$ = sub;
  }
  public changeBaseMap$ = new Subject();

  /**
 * 在地图上添加图层,图层类型可以是Image、Geometry、Feature、FeatureCollection,返回图层唯一的ID
 * @param {Image|Geometry|Feature|FeatureCollection} image 作为图层添加的图像数据
 * @param  {Object} [visParams] 可选参数,。属性:style(应用到图层的样式),palette(用于图层的调色板), crop(WKT类型的Geometry对象或gpkg文件路径),min, max, gamma, brightness
 * @param {String} [name] 可选参数,给予图层的名称。
 * @param {Boolean} [visible] 可选参数,该图层是否可见,默认为true
 * @return {String} 添加图层的Id
 */
  public addLayer(image: Image | Geometry | Feature | FeatureCollection | MosaicData | Mvt,
    visParams?: Object,
    name?: string,
    visible?: boolean): string {
    let addLayerParam: any = {};
    addLayerParam.id = Guid.newGuid();
    addLayerParam.image = image;
    addLayerParam.visParams = visParams;
    addLayerParam.name = name;
    addLayerParam.visible = visible;
    this.addLayerParams.push(addLayerParam);
    if (typeof process === 'undefined') {
      if (this.map && this.map.style._loaded) {
        this._addLayer(addLayerParam);
      }
    }
    else {
      this._addLayer(addLayerParam);
    }

    return addLayerParam.id;
  }
  /**
  * 在地图上添加自定义ui
  * @param {Widget} ui  自定义ui
  */
  public addUI(ui: Widget) {
    this.addUIParams.push(ui);
    if (this.map && this.map.style._loaded) {
      this._addUI(ui);
    }
  }

  /**
  * 移除地图上的自定义ui
  * @param {Widget} ui  自定义ui
  */
  public removeUI(ui: Widget) {
    this.removeUIParams.push(ui);
  }

  /**
  * 根据提供的ID移除图层
  * @param {String} Id 待删除图层的ID
  */
  public removeLayer(id: string) {
    this.removeLayerParams.push(id);
  }

  /**
     * 清空已添加的所有图层
     * @param {String} [param] 影像的url
     */
  public clear() {
    if (this.layerList) {
      this.layerList?.forEach((data: any) => {
        data?.onLoadCompleted(() => {
          data?.mapboxLayresId.forEach((lid: any) => {
            this.map.removeLayer(lid);
          });
          data?.mapboxSourcesId.forEach((sid: any) => {
            this.map.removeSource(sid);
          });
        });
      });
    }
    BatchProcessing.image.clearMap();
  }



  /**
     * 图层过滤显示
     * @param {String} id 图层的id
     * @param {String} classId 过滤的图层类别
     */
  public setFilter(id: string, classId: string) {
    MapUtil.setFilter(this, id, classId);
  }

  /**
   * 相机飞入到指定图层位置
   * @param {String | Array<number>} param 图层的Id
   */
  public flyto(param: string | Array<number>) {
    this.flytoParams.push(param);
    if (this.map && this.map.style._loaded) {
      this._flyto(param);
    }
  }

  //代替flyto,使用value接口
  /**
   * 相机飞入到指定图层位置
   * @param {Object} object 图层对象
   * @param {number} [zoom] 地图显示缩放级别(0-24)
   */
  public async centerObject(object: Object, zoom?: number) {
    await MapUtil.centerObject(this, object, zoom);
  }

  /**
   * 返回当前地图视图的近似像素比例,单位为米
   * @returns number
   */
  public getScale() {
    if (this.map && this.map.style._loaded) {
      let zoomLevel = Http.zoomLevel == -1?Math.round(this.map.getZoom()) + 1:Http.zoomLevel;
      if (zoomLevel < this.scaleDic.length) {
        return this.scaleDic[zoomLevel];
      }
      else {
        return null;
      }
    }
    else {
      return '地图尚未加载,无法获取地图分辨率';
    }
  }
  /**
   * 修改地图底图
   * @param {String} mapTypeId 可以是 "SATELLITE"、"ROADMAP" 或 "TERRAIN" 之一
   */
  public setOptions(mapTypeId:string): any {
    this.changeBaseMap$.next(mapTypeId);
    return null;
  }


  /**
   * 返回地图视图的当前缩放级别
   * @returns number
   */
  public getZoom() {
    if (this.map && this.map.style._loaded) {
      return this.map.getZoom();
    }
    else {
      if (this.setZoomParam) {
        return this.setZoomParam;
      }
      else {
        return 3;//默认级别
      }
    }
  }

  /**
   * 返回地图视图的地理中心
   * @returns Geometry.Point
   */
  public getCenter() {
    if (this.map && this.map.style._loaded) {
      const center = this.map.getCenter();
      return { lng: center.lng, lat: center.lat };
    }
    else {
      if (this.setCenterParams && !isNaN(this.setCenterParams['lon']) && !isNaN(this.setCenterParams['lat'])) {
        return { lng: this.setCenterParams['lon'], lat: this.setCenterParams['lat'] };
      }
      else {
        return { lng: 116.39880632, lat: 38.90487972 };//默认中心点
      }
    }
  }

  /**
   * 返回地图视图的地理边界
   * @returns GeoJSONGeometry|Array<Number>|String
   */
  public getBounds() {
    if (this.map && this.map.style._loaded) {
      return this.map.getBounds();
    }
    else {
      return '地图尚未加载,无法获取边界';
    }
  }

  /**
  * 设置地图中心显示
  * @param {Number} lon 地图显示中心点的经度
  * @param {Number} lat 地图显示中心点的经度
  * @param {Number} [zoom] 可选参数,地图显示缩放级别(0-24)
  */
  public setCenter(lon: number, lat: number, zoom?: number) {
    this.setCenterParams = { lon: lon, lat: lat, zoom: zoom };
    if (this.map && this.map.style._loaded) {
      this.map.setCenter([lon, lat]);
      if (zoom) {
        this.map.setZoom(zoom);
      }
    }
  }
  /**
   * 设置地图显示缩放级别
   * @param {Number} zoom 地图显示缩放级别(0-24)
   */
  public setZoom(zoom: number) {
    this.setZoomParam = zoom;
    if (this.map && this.map.style._loaded) {
      this.map.setZoom(zoom);
    }
  }

  /**
   * 放大地图
   */
  public zoomIn() {
    if (this.map && this.map.style._loaded) {
      return this.map.zoomIn();
    }
    else {
      return '地图尚未加载,无法放大地图';
    }
  }
  /**
   * 缩小地图
   */
  public zoomOut() {
    if (this.map && this.map.style._loaded) {
      return this.map.zoomOut();
    }
    else {
      return '地图尚未加载,无法缩小地图';
    }
  }

  /**
  * 返回绘制工具
  */
  public drawingTools() {
    //返回绘制工具
    if (!this.drawTools) {
      this.drawTools = new DrawingTools();
    }
    return this.drawTools;
  }

  /**
  * 设置地图控件显示隐藏
  * @param {boolean} all 是否显示所有控件。 true表示显示;false表示隐藏。
  * @param {boolean} layerList 是否显示图层控制控件。true表示显示;false表示隐藏。
  * @param {boolean} [zoomControl] 是否显示缩放控件。true表示显示;false表示隐藏。
  * @param {boolean} [scaleControl] 是否显示比例尺控件。 true表示显示;false表示隐藏。
  * @param {boolean} [mapTypeControl] 是否显示底图切换控件。true表示显示;false表示隐藏。
  * @param {boolean} [fullscreenControl] 是否显示全屏控件。true表示显示;false表示隐藏。
  * @param {boolean} [drawingToolsControl] 是否显示绘图控件。true表示显示;false表示隐藏。
  */
  public setControlVisibility(all?: boolean, layerList?: boolean, zoomControl?: boolean, scaleControl?: boolean, mapTypeControl?: boolean, fullscreenControl?: boolean, drawingToolsControl?: boolean) {
    //设置控件显示
    let controlVisibility = {};
    controlVisibility['all'] = all;
    controlVisibility['layerList'] = layerList;
    controlVisibility['zoomControl'] = zoomControl;
    controlVisibility['scaleControl'] = scaleControl;
    controlVisibility['mapTypeControl'] = mapTypeControl;
    controlVisibility['fullscreenControl'] = fullscreenControl;
    controlVisibility['drawingToolsControl'] = drawingToolsControl;
    this.controlVisibilityParams.push(controlVisibility);
  }

  getType(): string {
    return 'Map';
  }

  private _addLayer(options: any) {
    return MapUtil.addLayer(options, this);
  }




  private _flyto(param: string | Array<number>) {
    MapUtil.flyto(this, param);
  }

  private _addUI(ui: Widget) {
    if (this.mapUI) {
      if (!Http.isRunAddUICode) {
        Http.runDataSubject$.next({
          type: 'ui',
          content: Http.codeContent,
        });
        Http.isRunAddUICode = true;
      }
      if (ui.el) {
        let style = ui.style();
        // console.log('mapStyle:', style);
        if (!style.get('position')) {
          style.set('position', 'absolute');
          if (!style.get('right') && !style.get('bottom') && !style.get('left') && !style.get('top')) {
            style.set('left', '50%');
            style.set('top', '10px');
          }
        }
        style.set('z-index', '99');
      }
      this.mapUI.appendChild(ui.el as HTMLElement);
      if (ui['cht']) {
        (ui.el as HTMLElement).style.width = '300px';
        ui['cht']?.resize();
      }
    }
  }

  //运行结果调用
  public runResult(data: any) {
    if (data) {
      switch (data.type) {
        case "Geojson":
          {
            const { geojsonData, sourceId, layerId, style, render_sld } = data.params;
            MapUtil.addSourceByGeojson(this.map, geojsonData, sourceId, layerId, style, render_sld);//绘制图层
            data.bbox = turf.bbox(geojsonData);
          }
          break;
        case "Pbf":
          {
            const { serviceInfo, sourceId, layerId, visParams } = data.params;
            MapUtil.addSourceByPbf(this.map, serviceInfo, sourceId, layerId, visParams);//绘制图层
          }
          break;
        case "Url":
          {
            const {
              serviceInfo,
              sourceId,
              layerId,
              urlTiles,
              visible,
              visParams
            } = data.params;
            MapUtil.addSourceByUrl(
              this.map,
              serviceInfo,
              sourceId,
              layerId,
              urlTiles,
              visible,
              visParams
            );//绘制图层
          }
          break;
        case "Mvt":
          {
            const { serviceInfo, sourceId, layerId, visParams } = data.params;
            MapUtil.addSourceByMvt(this.map, serviceInfo, sourceId, layerId, visParams);//绘制图层
          }
          break;
      }
      if (data.bbox) {
        this.map.fitBounds(data.bbox);//视角飞入
      }
    }
  }

  //卷帘加的底图,为了适配屏幕布局变化进行resize
  public compareMapList: any[] = [];

  /**
  * 卷帘
  * @param {Image} left  左侧显示的Image实例
  * @param {Image} right 右侧显示的Image实例
  * @param {any[]} additionLayer 额外在左右两侧地图上都需要加的图层
  */
  public CompareImage(left: Image, right?: Image, additionLayer?: any[]) {
    this.compareMapList = [];
    let mapboxStyle;
    let mapStatus;
    if (typeof process === 'undefined') {
      //先清除原有地图
      // ui.root.clear();
      const link = document.createElement("link"); // 创建 link 元素
      link.rel = "stylesheet"; // 设置 link 的 rel 属性为 stylesheet
      link.href = "https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-compare/v0.4.0/mapbox-gl-compare.css"; // 设置 link 的 href 属性为 CSS 文件的 URL
      link.type = "text/css";
      (ui.root.el as any).appendChild(link); // 将 link 元素添加到指定元素的子节点中
      let mapStyle = {
        position: "absolute",
        top: 0,
        bottom: 0,
        width: "100%",
        height: "100%",
        "z-index": 1
      }
      let beforeDiv = ui.Panel(undefined, undefined, mapStyle);
      (beforeDiv.el as any).id = "before";
      let afterDiv = ui.Panel(undefined, undefined, mapStyle);
      (afterDiv.el as any).id = "after";
      let compareStyle = {
        height: "100%",
        width: "100%",
        position: "absolute",
        left: "0px",
        top: "0px",
        "z-index": 1
      }
      let compareDiv = ui.Panel([beforeDiv, afterDiv], ui.Panel.Layout.flow('horizontal'), compareStyle);
      (compareDiv.el as any).id = "comparison-container";
      ui.root.add(compareDiv);
      // 创建卷帘
      mapboxgl.accessToken = 'pk.eyJ1IjoiYXJhcGF5IiwiYSI6ImNsNXEyYXJhMDB2MWkzaWw4dWgxcWptOHYifQ.UYSWGUj_ufnOu-7KACtl4w';
      let center = this.getCenter();
      let zoom = this.getZoom();
      mapStatus = {
        center: [center.lng, center.lat],
        zoom: zoom
      }
      mapboxStyle = this.map.getStyle();
    }


    let beforeMap = new AddLayer("before", mapStatus, mapboxStyle);
    let afterMap = new AddLayer("after", mapStatus, mapboxStyle);
    this.compareMapList.push(beforeMap.map);
    this.compareMapList.push(afterMap.map);
    let leftLayer = undefined;
    let rightLayer = undefined;
    if (left) {
      let leftLayerid = beforeMap.addLayer(left);
      if (typeof process === 'undefined') {
        leftLayer = beforeMap.layerList.find((v: any) => { return v.id == leftLayerid });
        // 加上额外的图层
        if (additionLayer && additionLayer.length > 0) {
          leftLayer.onLoadCompleted(() => {
            additionLayer.forEach(la => {
              let tempLayerid = beforeMap.addLayer(la, { style: { polygonFillOpacity: 0 } });
              let tempLayer = beforeMap.layerList.find((v: any) => { return v.id == tempLayerid });
              //每次都把新加的图层置于顶层
              for (let x = 0; x < tempLayer.mapboxLayresId.length; x++) {
                beforeMap.map.moveLayer(tempLayer.mapboxLayresId[x], undefined);
              }
            })
          })

        }
      }
    }
    // MapSdk.compareMapSubject$.next([beforeMap, afterMap]);
    if (right) {
      let rightLayerid = afterMap.addLayer(right);
      if (typeof process === 'undefined') {
        rightLayer = afterMap.layerList.find((v: any) => { return v.id == rightLayerid });
        // 加上额外的图层
        if (additionLayer && additionLayer.length > 0) {
          rightLayer.onLoadCompleted(() => {
            additionLayer.forEach(la => {
              let tempLayerid = afterMap.addLayer(la, { style: { polygonFillOpacity: 0 } });
              let tempLayer = afterMap.layerList.find((v: any) => { return v.id == tempLayerid });
              //每次都把新加的图层置于顶层
              for (let x = 0; x < tempLayer.mapboxLayresId.length; x++) {
                afterMap.map.moveLayer(tempLayer.mapboxLayresId[x], undefined);
              }
            })
          })

        }
      }
    }
    if (leftLayer && !rightLayer) {
      beforeMap.flyto(leftLayer.id);
    } else if (rightLayer) {
      afterMap.flyto(rightLayer.id);
    }

    const container = '#comparison-container';
    if (typeof process === 'undefined') {
      const map = new Compare(beforeMap.map, afterMap.map, container, {});
    }
    //   ///////////////////////////////////////////////////////用ui.Map来实现
    //   //先清除原有地图
    //   ui.root.clear();
    //   const link = document.createElement("link"); // 创建 link 元素
    //   link.rel = "stylesheet"; // 设置 link 的 rel 属性为 stylesheet
    //   link.href = "https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-compare/v0.4.0/mapbox-gl-compare.css"; // 设置 link 的 href 属性为 CSS 文件的 URL
    //   link.type = "text/css";
    //   (ui.root.el as any).appendChild(link); // 将 link 元素添加到指定元素的子节点中
    //   let center = this.getCenter();
    //   let zoom = this.getZoom();
    //   let mapStyle = {
    //     position: "absolute",
    //     top: 0,
    //     bottom: 0,
    //     width: "100%",
    //     height: "100%",
    //     "z-index": 1
    //   }
    //   let beforeDiv = ui.Map({ lon: center.lng, lat: center.lat, zoom: zoom }, undefined, mapStyle);
    //   beforeDiv.setControlVisibility(true, true, false, false, true, false, false);
    //   //卷帘左侧底图切换按钮要显示在最左
    //   beforeDiv.toolBtnLocat.baseMapLocat = 'bottom-left';
    //   //卷帘左侧图层按钮要显示在最右
    //   beforeDiv.toolBtnLocat.layerListLocat = "top-left";
    //   let afterDiv = ui.Map({ lon: center.lng, lat: center.lat, zoom: zoom }, undefined, mapStyle);
    //   afterDiv.setControlVisibility(true, true, false, false, true, false, false);

    //   let compareStyle = {
    //     height: "100%",
    //     width: "100%",
    //     position: "absolute",
    //     left: "0px",
    //     top: "0px",
    //     "z-index": 1
    //   }
    //   let compareDiv = ui.Panel([beforeDiv, afterDiv], ui.Panel.Layout.flow('horizontal'), compareStyle);
    //   (compareDiv.el as any).id = "comparison-container";
    //   ui.root.add(compareDiv);

    //   // 创建卷帘

    //   let leftLayerId: string = undefined;
    //   let rightLayerId: string = undefined;
    //   if (left) {
    //     leftLayerId = beforeDiv.addLayer(left);

    //     // 加上额外的图层
    //     if (additionLayer && additionLayer.length > 0) {
    //         beforeDiv.addAdditionLayer(beforeDiv, leftLayerId, additionLayer);
    //     }

    //   }
    //   if (right) {
    //     rightLayerId = afterDiv.addLayer(right);
    //     // 加上额外的图层
    //     if (additionLayer && additionLayer.length > 0) {

    //         afterDiv.addAdditionLayer(afterDiv, rightLayerId, additionLayer);
    //     }
    //   }
    //   if (leftLayerId && !rightLayerId) {
    //     beforeDiv.flyto(leftLayerId);
    //   } else if (rightLayerId) {
    //     afterDiv.flyto(rightLayerId);
    //   }

    //   const container = '#comparison-container';

    //   Compare.prototype._setPosition = function(x: any){
    //     // console.log("调用了重写的comapare函数")
    //     x = Math.min(x, this._horizontal
    //       ? this._bounds.height
    //       : this._bounds.width);
    //     var pos = this._horizontal
    //       ? 'translate(0, ' + x + 'px)'
    //       : 'translate(' + x + 'px, 0)';
    //     this._controlContainer.style.transform = pos;
    //     this._controlContainer.style.WebkitTransform = pos;
    //     var clipA = this._horizontal
    //       ? 'rect(0, 999em, ' + x + 'px, 0)'
    //       : 'rect(0, ' + x + 'px, ' + this._bounds.height + 'px, 0)';
    //     var clipB = this._horizontal
    //       ? 'rect(' + x + 'px, 999em, ' + this._bounds.height + 'px,0)'
    //       : 'rect(0, 999em, ' + this._bounds.height + 'px,' + x + 'px)';

    //     this._mapA.getContainer().style.clip = clipA;
    //     this._mapB.getContainer().style.clip = clipB;
    //     if(this.options.divA){
    //       this.options.divA.el.style.clip = clipA;
    //     }
    //     if(this.options.divB){
    //       this.options.divB.el.style.clip = clipB;
    //     }
    //     this.currentPosition = x;
    //   }

    //   const map = new Compare(beforeDiv.map, afterDiv.map, container, {divA: beforeDiv, divB: afterDiv});
    // /////////////////////////////////////////////////////////////////////

  }

  //在指定id的图层加载完之后再加载附加图层
  public addAdditionLayer(object: any, id: string, additionLayer: any[]) {
    // console.log("objjjjjjjjjjjjjjj", this.layerList[0])
    if (this.map && this.map.style._loaded) {
      let res = this.layerList.find((v: any) => v.id == id);
      // console.log("add addtionlayer....res", res, id)
      if (res && res.layer) {
        res.layer.onLoadCompleted(() => {
          additionLayer.forEach(la => {
            let tempLayerId = this.addLayer(la);
            let tempLayer = this.layerList.find((v: any) => { return v.id == tempLayerId });
            if (tempLayer) {
              //每次都把新加的图层置于顶层
              for (let x = 0; x < tempLayer.layer.mapboxLayresId.length; x++) {
                this.map.moveLayer(tempLayer.layer.mapboxLayresId[x], undefined);
              }
            }
          })
        });
      }
    }

  }

}