import esriLoader from "esri-loader";
import {
  MapClass,
  MapOverLayer,
  MapType,
  MapExtent,
  MapLineType,
  CoorSystem,
  MapPointStyle,
} from "./mapClass";
import remoteLoad from "./remoteLoad.js";
import CoordsConvertUtil from "./coordsConvert";
export default class TslMapClient {
  // 全局地图类 this.mapClass
  mapClass = new MapClass();
  // 地图配置
  mapParams = null;
  // 地图点击事件
  mapPointClicked = null;
  // 地图聚合
  cluster = null;
  
  /**
   * 创建地图
   * @param {string} container 地图容器
   * @param {} mParams 地图配置
   * @param {} extent 初始化地图范围 {xmin:0,ymin:0,xmax:0,ymax:0}
   */
  async initMap(container, mParams, extent) {
    let _that = this;
    this.mapParams = mParams;
    let mExtent = new MapExtent(
      extent.xmin,
      extent.ymin,
      extent.xmax,
      extent.ymax
    );
    this.mapClass = new MapClass(
      container,
      this.mapParams.url,
      mExtent,
      this.mapParams.minzoom,
      this.mapParams.maxZoom
    );
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        const options = {
          url: this.mapParams.apiUrl,
        };
        let loadEsri = await esriLoader.loadScript(options);
        esriLoader.loadCss(this.mapParams.apiCss);

        let [
          Map,
          Extent,
          ArcGISTiledMapServiceLayer,
          Point,
          SpatialReference,
        ] = await esriLoader.loadModules([
          "esri/map",
          "esri/geometry/Extent",
          "esri/layers/ArcGISTiledMapServiceLayer",
          "esri/geometry/Point",
          "esri/SpatialReference",
        ]);

        this.mapClass.map = new Map(container, {
          logo: false,
          slider: false,
          fitExtent: true,
          maxZoom: 7, // 最大空间等级
          // extent: new Extent({
          //   xmin: this.mapClass.mapExtent.xmin,
          //   ymin: this.mapClass.mapExtent.ymin,
          //   xmax: this.mapClass.mapExtent.xmax,
          //   ymax: this.mapClass.mapExtent.ymax
          // })
        });

        let spatialRef = new SpatialReference({
          wkid: 4326,
        });
        let spatialRefName;
        if (this.mapParams.spatialReference) {
          spatialRefName = this.mapParams.spatialReference.name;
        }
        switch (spatialRefName) {
          case CoorSystem.sh_54:
            spatialRef = new SpatialReference(
              this.mapParams.spatialReference.content
            );
            break;
        }
        let baseMapLayer = new ArcGISTiledMapServiceLayer(this.mapParams.url);
        this.mapClass.map.addLayer(baseMapLayer);

        this.mapClass.map.centerAndZoom(
          new Point(
            (this.mapClass.mapExtent.xmin + this.mapClass.mapExtent.xmax) / 2,
            (this.mapClass.mapExtent.ymin + this.mapClass.mapExtent.ymax) / 2,
            spatialRef
          ),
          this.mapParams.zoom
        );

        this.mapClass.map.on("zoom", function(e) {});
        this.mapClass.map.setMapCursor("default");
        this.mapClass.map.on("click", function(ev) {
          // console.log(ev.mapPoint.x + ',' + ev.mapPoint.y)
        });

        return this.mapClass.map;

        break;
      case MapType.Gaode:
        let remoteLoadGaode = await remoteLoad(this.mapClass.baseMapURL);
        // mExtent 转高德
        let pt = CoordsConvertUtil.wgs84ToGaode([
          [this.mapClass.mapExtent.xmin, this.mapClass.mapExtent.ymin],
          [this.mapClass.mapExtent.xmax, this.mapClass.mapExtent.ymax],
        ]);

        this.mapClass.map = new window.AMap.Map(container, {
          resizeEnable: true,
          mapStyle: this.mapParams.mapstyle,
          center: [(pt[0][0] + pt[1][0]) / 2, (pt[0][1] + pt[1][1]) / 2],
          zooms: this.mapParams.zooms,
          zoom:
            this.mapParams.viewMode === "2D"
              ? Math.round(this.mapParams.zoom - 0.5)
              : 18,
          viewMode: this.mapParams.viewMode,
          pitch: this.mapParams.pitch,
          expandZoomRange: this.mapParams.expandZoomRange,
        });
        let selectlayer = new window.AMap.OverlayGroup();
        if (this.mapParams.isShowTextAtMaxZoom) {
          this.mapClass.map.on("zoomchange", function() {
            _that.showLayerAtMaxZoom();
          });
        }
        return this.mapClass.map;
        break;
      case MapType.GA:
        let pts = CoordsConvertUtil.wgs84ToGaode([
          [this.mapClass.mapExtent.xmin, this.mapClass.mapExtent.ymin],
          [this.mapClass.mapExtent.xmax, this.mapClass.mapExtent.ymax],
        ]);

        let centerX = (pts[0][0] + pts[1][0]) / 2;
        let centerY = (pts[0][1] + pts[1][1]) / 2;
        setTimeout(() => {
          this.mapClass.map = new window.IMAP.Map(container, {
            minZoom: this.mapParams.zooms[0],
            maxZoom: this.mapParams.zooms[1],
            zoom: this.mapParams.zoom,
            center: new window.IMAP.LngLat(centerX, centerY),
          });
          if (this.mapParams.isShowTextAtMaxZoom) {
            this.mapClass.map.addEventListener(
              window.IMAP.Constants.ZOOM_END,
              function() {
                _that.showLayerAtMaxZoom();
              }
            );
          }
          return this.mapClass.map;
        }, 300);
        break;
      case MapType.Tianditu:
        setTimeout(() => {
          this.mapClass.map = window.L.map(container, {
            crs: window.L.CRS.CustomEPSG4326,
            center: [
              (this.mapClass.mapExtent.xmin + this.mapClass.mapExtent.xmax) / 2,
              (this.mapClass.mapExtent.ymin + this.mapClass.mapExtent.ymax) / 2,
            ],
            zoom: this.mapParams.zoom,
            minZoom: this.mapParams.zooms[0],
            maxZoom: this.mapParams.zooms[1],
            zoomControl: false,
            // trackResize: true
          });
          // 添加底图
          let layer = new window.L.GXYZ(this.mapParams.url);
          this.mapClass.map.addLayer(layer);

          // // 添加注记图层
          // var labelLayer = new window.L.GWVTAnno('GWVTAnno')
          // var dataSource = new window.Custom.URLDataSource()
          // /* eslint-disable-next-line */
          // dataSource.url = 'http://118.178.118.175/mapserver/label/zjvmap/getDatas?x=${x}&y=${y}&l=${z}&styleId=tdt_biaozhunyangshi_2017'
          // labelLayer.addDataSource(dataSource)
          // this.mapClass.map.addLayer(labelLayer)

          if (this.mapParams.isShowTextAtMaxZoom) {
            this.mapClass.map.on("zoomend", function() {
              this.showLayerAtMaxZoom();
            });
          }
          return this.mapClass.map;
        }, 300);

        break;
    }
  }

  /**
   * 添加点图层
   * @param {string} layername 图层名
   * @param {[{}]} geoObj 构成图层的几何集合 {name: '', deviceID: '', longitude:'',latitude:'',type:'',iconUrl:''}
   * @param {Boolean} isLabel 是否标注
   * @param {Boolean} isClickable 是否可以点击
   */
  async addPointsLayer(layername, geoObj, isLabel, isClickable) {
    let _that = this;
    if (this.mapClass.map === undefined || geoObj == null) {
      return;
    }
    if (geoObj.length > 0) {
      // showWeb 放出来
      let markerList = [];
      this.mapClass.layerDatas.push({
        layername: layername,
        data: geoObj,
      });
      switch (this.mapParams.mapType) {
        case MapType.Esri:
          let [
            GraphicsLayer,
            Point,
            Graphic,
            PictureMarkerSymbol,
            TextSymbol,
            SpatialReference,
          ] = await esriLoader.loadModules([
            "esri/layers/GraphicsLayer",
            "esri/geometry/Point",
            "esri/graphic",
            "esri/symbols/PictureMarkerSymbol",
            "esri/symbols/TextSymbol",
            "esri/SpatialReference",
          ]);

          let glayer = new GraphicsLayer();
          let statesArr = [];
          for (let i = 0, len = geoObj.length; i < len; i++) {
            if (geoObj[i].longitude == null || geoObj[i].latitude == null)
              continue;
            if (geoObj[i].longitude === 0 || geoObj[i].latitude === 0) continue;
            let xCoor = geoObj[i].longitude;
            let yCoor = geoObj[i].latitude;
            let spatialRef = new SpatialReference({
              wkid: 4326,
            });

            /**
             * spatialReference 参考系，84参考系下默认可以不配置
             */
            let spatialRefName;
            if (this.mapParams.spatialReference) {
              spatialRefName = this.mapParams.spatialReference.name;
            }
            switch (spatialRefName) {
              case CoorSystem.sh_54:
                spatialRef = new SpatialReference(
                  this.mapParams.spatialReference.content
                );
                break;
            }
            let pt = new Point(xCoor, yCoor, spatialRef);
            let marker = new Graphic(pt);
            // 地图点击回调数据geoObj[i]
            marker.setAttributes(geoObj[i]);

            let picSymbol = new PictureMarkerSymbol(
              geoObj[i].mapPointStyle.baseUrl,
              geoObj[i].mapPointStyle.width,
              geoObj[i].mapPointStyle.height
            );
            marker.setSymbol(picSymbol);
            glayer.add(marker);
          }
          this.mapClass.map.addLayer(glayer);
          // if (isClickable) {
          glayer.on("click", function(e) {
            if (
              _that.mapPointClicked !== undefined &&
              _that.mapPointClicked !== null
            ) {
              // 地图点击回调数据
              _that.mapPointClicked(e.graphic.attributes);
            }
          });

          glayer.on("mouse-over", function(e) {
            _that.mapClass.map.setMapCursor("pointer");
          });
          glayer.on("mouse-out", function(e) {
            _that.mapClass.map.setMapCursor("default");
          });
          this.mapClass.layers.push(new MapOverLayer(layername, glayer, true));

          break;
        case MapType.Gaode:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            if (geoObj[i].longitude == null || geoObj[i].latitude == null)
              continue;
            if (geoObj[i].longitude === 0 || geoObj[i].latitude === 0) continue;

            let pt = CoordsConvertUtil.wgs84ToGaode([
              [geoObj[i].longitude, geoObj[i].latitude],
            ]);
            let content = `<div class="${geoObj[i].mapPointStyle.iconClass}"></div>`;
            let marker = new window.AMap.Marker({
              map: this.mapClass.map,
              position: [pt[0][0], pt[0][1]],
              extData: geoObj[i],
              content: content,
              offset: new window.AMap.Pixel(
                geoObj[i].mapPointStyle.xOffset,
                geoObj[i].mapPointStyle.yOffset
              ),
            });

            // marker.setMap(this.mapClass.map)
            markerList.push(marker);
            if (isClickable) {
              marker.on("click", function(e) {
                if (
                  _that.mapPointClicked !== undefined &&
                  _that.mapPointClicked !== null
                ) {
                  _that.mapPointClicked(e.target.getExtData());
                }
              });
            }
            if (this.mapParams.isShowTextAtMaxZoom && isLabel) {
              let tLayer = this.getLyrByName(layername + "_label");
              if (tLayer === undefined) {
                tLayer = [];
                this.mapClass.layers.push(
                  new MapOverLayer(layername + "_label", tLayer, true)
                );
              }
              let text = new window.AMap.Text({
                // draggable: true,
                text: geoObj[i].name,
                textAlign: "center",
                verticalAlign: "middle",
                style: {
                  backgroundColor: "#091e38",
                  padding: "5px 10px",
                  color: "white",
                },
                offset: new window.AMap.Pixel(20, 30),
                position: [pt[0][0], pt[0][1]],
              });
              text.setMap(null);
              tLayer.push(text);
            }
          }
          this.mapClass.layers.push(
            new MapOverLayer(layername, markerList, true)
          );
          break;
        case MapType.GA:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            if (geoObj[i].longitude == null || geoObj[i].latitude == null)
              continue;
            if (geoObj[i].longitude === 0 || geoObj[i].latitude === 0) continue;

            let pt = CoordsConvertUtil.wgs84ToGaode([
              [geoObj[i].longitude, geoObj[i].latitude],
            ]);
            let opts = new window.IMAP.MarkerOptions();
            opts.anchor = window.IMAP.Constants.BOTTOM_CENTER;

            opts.icon = new window.IMAP.Icon(geoObj[i].baseUrl, {
              size: new window.IMAP.Size(
                geoObj[i].mapPointStyle.width,
                geoObj[i].mapPointStyle.height
              ),
            });

            opts.editabled = false;
            opts.visible = true;
            let marker = new window.IMAP.Marker(
              new window.IMAP.LngLat(pt[0][0], pt[0][1]),
              opts
            );
            marker.D = geoObj[i];
            this.mapClass.map.getOverlayLayer().addOverlay(marker, true);
            markerList.push(marker);
            if (isClickable) {
              marker.addEventListener(window.IMAP.Constants.CLICK, function(
                evt
              ) {
                if (
                  _that.mapPointClicked !== undefined &&
                  _that.mapPointClicked !== null
                ) {
                  _that.mapPointClicked(evt.target.D);
                }
              });
            }

            if (this.mapParams.isShowTextAtMaxZoom && isLabel) {
              let tLayer = this.getLyrByName(layername + "_label");
              if (tLayer === undefined) {
                tLayer = [];
                this.mapClass.layers.push(
                  new MapOverLayer(layername + "_label", tLayer, true)
                );
              }
              let text = new window.IMAP.Label("", {
                type: window.IMAP.Constants.OVERLAY_LABEL_HTML,
                position: new window.IMAP.LngLat(pt[0][0], pt[0][1]),
                offset: new window.IMAP.Pixel(10, 20),
                anchor: window.IMAP.Constants.BOTTOM_CENTER,
              });
              let content =
                '<div class="textContainer">' + geoObj[i].name + "</div>";
              text.setContent(content);
              tLayer.push(text);
            }
          }
          this.mapClass.layers.push(
            new MapOverLayer(layername, markerList, true)
          );
          break;
        case MapType.Tianditu:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            if (geoObj[i].longitude == null || geoObj[i].latitude == null)
              continue;
            if (geoObj[i].longitude === 0 || geoObj[i].latitude === 0) continue;

            let customIconDiv = window.L.divIcon({
              className: geoObj[i].iconClass,
              iconSize: [
                geoObj[i].mapPointStyle.width,
                geoObj[i].mapPointStyle.height,
              ],
            });

            let marker = window.L.marker(
              [geoObj[i].latitude, geoObj[i].longitude],
              {
                icon: customIconDiv,
                alt: geoObj[i],
              }
            );

            markerList.push(marker);

            if (isClickable) {
              marker.on("click", function(e) {
                if (
                  _that.mapPointClicked !== undefined &&
                  _that.mapPointClicked !== null
                ) {
                  _that.mapPointClicked(e.target.options.alt);
                }
              });
            }
            if (this.mapParams.isShowTextAtMaxZoom && isLabel) {
              let tLayer = this.getLyrByName(layername + "_label");
              if (tLayer === undefined) {
                tLayer = window.L.layerGroup();
                this.mapClass.layers.push(
                  new MapOverLayer(layername + "_label", tLayer, true)
                );
              }

              let textDiv = window.L.divIcon({
                html: geoObj[i].name,
                className: "textContainer",
                iconAnchor: [35, -23],
              });
              let text = window.L.marker(
                [geoObj[i].latitude, geoObj[i].longitude],
                {
                  icon: textDiv,
                }
              );

              tLayer.addLayer(text);
            }
          }
          let groupLayer = window.L.layerGroup(markerList).addTo(
            this.mapClass.map
          );
          this.mapClass.layers.push(
            new MapOverLayer(layername, groupLayer, true)
          );
          break;
      }
    }
  }

  /**
   * 添加线图层
   * @param {string} layername 图层名
   * @param {[]} geoObj 构成图层的几何集合 {name: '', deviceID: '', path: [[],[]]}
   * @param {MapLineStyle} style 线样式
   * @param {Boolean} isLabel 是否标注
   */
  async addLinesLayer(layername, geoObj, style, isLabel) {
    if (this.mapClass.map === undefined || geoObj == null) {
      return;
    }
    if (geoObj.length > 0) {
      let markerlist = [];
      this.mapClass.layerDatas.push({
        layername: layername,
        data: geoObj,
      });
      switch (this.mapParams.mapType) {
        case MapType.Esri:
          let [
            GraphicsLayer,
            Polyline,
            Graphic,
            SimpleLineSymbol,
            Color,
          ] = await esriLoader.loadModules([
            "esri/layers/GraphicsLayer",
            "esri/geometry/Polyline",
            "esri/graphic",
            "esri/symbols/SimpleLineSymbol",
            "esri/Color",
          ]);

          let glayer = new GraphicsLayer();
          for (let i = 0, len = geoObj.length; i < len; i++) {
            let paths = geoObj[i].path;
            let polyline = new Polyline(paths);
            let marker = new Graphic(polyline);

            let lineStyle =
              style.lineType === MapLineType.Dashed
                ? SimpleLineSymbol.STYLE_DASH
                : SimpleLineSymbol.STYLE_SOLID;

            let fcolor = new Color(style.color);
            if (style.opacity !== 1) {
              fcolor.a = style.opacity;
            }

            let lSymbol = new SimpleLineSymbol(lineStyle, fcolor, style.width);
            marker.setSymbol(lSymbol);
            glayer.add(marker);
          }
          this.mapClass.map.addLayer(glayer);
          this.mapClass.layers.push(new MapOverLayer(layername, glayer, true));

          break;
        case MapType.Gaode:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            let pts = CoordsConvertUtil.wgs84ToGaode(geoObj[i].path);
            let centerX = (pts[0][0] + pts[pts.length - 1][0]) / 2;
            let centerY = (pts[0][1] + pts[pts.length - 1][1]) / 2;

            let polyline = new window.AMap.Polyline({
              path: pts,
            });

            polyline.setOptions({
              strokeWeight: style.width,
              strokeOpacity: style.opacity,
              strokeColor: style.color,
              // lineCap: 'round',
              strokeStyle: style.lineType.toLowerCase(),
            });
            polyline.setMap(this.mapClass.map);
            markerlist.push(polyline);

            if (this.mapParams.isShowTextAtMaxZoom && isLabel) {
              let tLayer = this.getLyrByName(layername + "_label");
              if (tLayer === undefined) {
                tLayer = [];
                this.mapClass.layers.push(
                  new MapOverLayer(layername + "_label", tLayer, true)
                );
              }

              let text = new window.AMap.Text({
                text: geoObj[i].name,
                textAlign: "center",
                verticalAlign: "middle",
                style: {
                  backgroundColor: "#091e38",
                  padding: "5px 10px",
                  color: "white",
                },
                offset: new window.AMap.Pixel(20, 30),
                position: [centerX, centerY],
              });

              text.setMap(null);
              tLayer.push(text);
            }
          }
          this.mapClass.layers.push(
            new MapOverLayer(layername, markerlist, true)
          );
          break;
        case MapType.GA:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            let pts = CoordsConvertUtil.wgs84ToGaode(geoObj[i].path);
            let path = [];
            for (let i = 0; i < pts.length; i++) {
              path.push(new window.IMAP.LngLat(pts[i][0], pts[i][1]));
            }
            let centerX = (pts[0][0] + pts[pts.length - 1][0]) / 2;
            let centerY = (pts[0][1] + pts[pts.length - 1][1]) / 2;

            let polyline = new window.IMAP.Polyline(path, {
              strokeWeight: style.width,
              strokeOpacity: style.opacity,
              strokeColor: style.color,
              // lineCap: 'round',
              strokeStyle:
                style.lineType.toLowerCase() === "dashed"
                  ? window.IMAP.Constants.OVERLAY_LINE_DASHED
                  : window.IMAP.Constants.OVERLAY_LINE_SOLID,
            });

            this.mapClass.map.getOverlayLayer().addOverlay(polyline, true);
            markerlist.push(polyline);

            if (this.mapParams.isShowTextAtMaxZoom && isLabel) {
              let tLayer = this.getLyrByName(layername + "_label");
              if (tLayer === undefined) {
                tLayer = [];
                this.mapClass.layers.push(
                  new MapOverLayer(layername + "_label", tLayer, true)
                );
              }

              let text = new window.IMAP.Label("", {
                type: window.IMAP.Constants.OVERLAY_LABEL_HTML,
                position: new window.IMAP.LngLat(centerX, centerY),
                offset: new window.IMAP.Pixel(10, 20),
                anchor: window.IMAP.Constants.BOTTOM_CENTER,
              });
              let content =
                '<div class="textContainer">' + geoObj[i].name + "</div>";
              text.setContent(content);
              tLayer.push(text);
            }
          }
          this.mapClass.layers.push(
            new MapOverLayer(layername, markerlist, true)
          );
          break;
        case MapType.Tianditu:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            let latlngs = geoObj[i].path.map(function(val) {
              return [val[1], val[0]];
            });
            let polyline = window.L.polyline(latlngs, {
              color: style.color,
              dashArray:
                style.lineType.toLowerCase() === "dashed" ? [20, 20] : null,
              weight: style.width,
              opacity: style.opacity,
            });

            markerlist.push(polyline);

            if (this.mapParams.isShowTextAtMaxZoom && isLabel) {
              let tLayer = this.getLyrByName(layername + "_label");
              if (tLayer === undefined) {
                tLayer = window.L.layerGroup();
                this.mapClass.layers.push(
                  new MapOverLayer(layername + "_label", tLayer, true)
                );
              }
              let pathLen = geoObj[i].path.length;

              let centerY =
                (geoObj[i].path[0][0] + geoObj[i].path[pathLen - 1][0]) / 2;
              let centerX =
                (geoObj[i].path[0][1] + geoObj[i].path[pathLen - 1][1]) / 2;

              let textDiv = window.L.divIcon({
                html: geoObj[i].name,
                className: "textContainer",
                iconAnchor: [35, -10],
              });
              let text = window.L.marker([centerY, centerX], {
                icon: textDiv,
              });

              tLayer.addLayer(text);
            }
          }
          let groupLayer = window.L.layerGroup(markerlist).addTo(
            this.mapClass.map
          );
          this.mapClass.layers.push(
            new MapOverLayer(layername, groupLayer, true)
          );
          break;
      }
    }
  }

  /**
   * 画一个区域面
   * @param {*} layername 线条名称
   * @param {*} geoObj 坐标数据
   * @param {*} style 样式
   * @returns
   */
  async addPolygonLayer(layername, geoObj, style) {
    if (this.mapClass.map === undefined || geoObj == null) {
      return;
    }
    if (geoObj.length > 0) {
      let markerlist = [];
      this.mapClass.layerDatas.push({
        layername: layername,
        data: geoObj,
      });
      switch (this.mapParams.mapType) {
        case MapType.Esri:
          let [
            GraphicsLayer,
            Polygon,
            Graphic,
            SimpleFillSymbol,
            SimpleLineSymbol,
            Color,
          ] = await esriLoader.loadModules([
            "esri/layers/GraphicsLayer",
            "esri/geometry/Polygon",
            "esri/graphic",
            "esri/symbols/SimpleFillSymbol",
            "esri/symbols/SimpleLineSymbol",
            "esri/Color",
          ]);

          let glayer = new GraphicsLayer();
          for (let i = 0, len = geoObj.length; i < len; i++) {
            let polygon = new Polygon(geoObj[i]);
            let marker = new Graphic(polygon);

            let fillStyle = SimpleFillSymbol.STYLE_NULL;
            let lineStyle = SimpleLineSymbol.STYLE_NULL;
            let fcolor = new Color([255, 255, 255, 0]);
            let outlinecolor = new Color([255, 255, 255, 0]);
            let strokeWeight = 0;

            if (style.strokeType === MapLineType.Solid) {
              lineStyle = SimpleLineSymbol.STYLE_SOLID;
            } else if (style.strokeType === MapLineType.Dashed) {
              lineStyle = SimpleLineSymbol.STYLE_DASH;
            }

            if (style.fillColor != null) {
              fcolor = new Color(style.fillColor);
              fillStyle = SimpleFillSymbol.STYLE_SOLID;
            }
            if (style.fillOpacity !== 1) {
              fcolor.a = style.fillOpacity;
            }
            if (style.strokeColor != null) {
              outlinecolor = new Color(style.strokeColor);
            }
            if (style.strokeOpacity !== 1) {
              outlinecolor.a = style.strokeOpacity;
            }
            if (style.strokeWeight !== 0) {
              strokeWeight = style.strokeWeight;
            }

            let fSymbol = new SimpleFillSymbol(
              fillStyle,
              new SimpleLineSymbol(lineStyle, outlinecolor, strokeWeight),
              fcolor
            );

            marker.setSymbol(fSymbol);
            glayer.add(marker);
          }

          this.mapClass.map.addLayer(glayer, 0);
          this.mapClass.layers.push(new MapOverLayer(layername, glayer, true));

          break;
        case MapType.Gaode:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            for (let j = 0, lens = geoObj[i].length; j < lens; j++) {
              let pts = CoordsConvertUtil.wgs84ToGaode(geoObj[i][j]);
              let polygon = new window.AMap.Polygon({
                path: pts,
              });

              if (style.fillColor != null) {
                polygon.setOptions({
                  fillColor: style.fillColor,
                });
              }
              if (style.fillOpacity !== 1) {
                polygon.setOptions({
                  fillOpacity: style.fillOpacity,
                });
              }
              if (style.strokeColor != null) {
                polygon.setOptions({
                  strokeColor: style.strokeColor,
                });
              }
              if (style.strokeOpacity !== 1) {
                polygon.setOptions({
                  strokeOpacity: style.strokeOpacity,
                });
              }
              if (style.strokeWeight !== 0) {
                polygon.setOptions({
                  strokeWeight: style.strokeWeight,
                });
              }
              if (style.strokeType === MapLineType.Dashed) {
                polygon.setOptions({
                  strokeStyle: "dashed",
                  strokeDasharray: [10, 5],
                });
              }
              polygon.setMap(this.mapClass.map);
              markerlist.push(polygon);
              polygon.on("click", function(e) {
                let strokeColor0 = e.target.Ge.strokeColor;
                let strokeWeight0 = e.target.Ge.strokeWeight;
                let villageInfo = e.target.getExtData();
                let param = {
                  villageName: villageInfo.spaceName,
                  villageID: villageInfo.spaceId,
                  level: villageInfo.spaceType,
                };
                let routerArr = window.location.hash.split("/");
                let routerInfo = routerArr[routerArr.length - 1];
                if (routerInfo === "allState") {
                  window.clickVillageWindowShow(param);
                  window.clickVillageWindow(param);
                }
              });
            }
          }
          this.mapClass.layers.push(
            new MapOverLayer(layername, markerlist, true)
          );
          break;
        case MapType.GA:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            for (let j = 0, lens = geoObj[i].length; j < lens; j++) {
              let pts = CoordsConvertUtil.wgs84ToGaode(geoObj[i][j]);
              let path = [];
              for (let i = 0; i < pts.length; i++) {
                let x = pts[i][0];
                let y = pts[i][1];
                path.push(new window.IMAP.LngLat(x, y));
              }
              let polygon = new window.IMAP.Polygon(path, {
                fillColor: style.fillColor,
                fillOpacity: style.fillOpacity,
                strokeColor: style.strokeColor,
                strokeOpacity: style.strokeOpacity,
                strokeWeight: style.strokeWeight,
                strokeStyle:
                  style.strokeType === MapLineType.Dashed
                    ? window.IMAP.Constants.OVERLAY_LINE_DASHED
                    : window.IMAP.Constants.OVERLAY_LINE_SOLID,
              });

              this.mapClass.map.getOverlayLayer().addOverlay(polygon, true);
              markerlist.push(polygon);
            }
          }
          this.mapClass.layers.push(
            new MapOverLayer(layername, markerlist, true)
          );
          break;
        case MapType.Tianditu:
          for (let i = 0, len = geoObj.length; i < len; i++) {
            for (let j = 0, lens = geoObj[i].length; j < lens; j++) {
              let latlngs = geoObj[i][j].map(function(val) {
                return [val[1], val[0]];
              });
              let polygon = window.L.polygon(latlngs, {
                color: style.strokeColor,
                fillColor: style.fillColor,
                fillOpacity: style.fillOpacity,
                weight: style.strokeWeight,
              });

              markerlist.push(polygon);
            }
          }
          let groupLayer = window.L.layerGroup(markerlist).addTo(
            this.mapClass.map
          );
          this.mapClass.layers.push(
            new MapOverLayer(layername, groupLayer, true)
          );
          break;
      }
    }
  }

  /**
   * 通过图层名获取图层index
   * @param {string} lyrname 返回-1则找不到
   */
  getLyrIndexByName(lyrname) {
    for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
      if (this.mapClass.layers[i].name === lyrname) {
        return i;
      }
    }
    return -1;
  }

  /**
   * 清除点/线/面图层
   * @param {string} layername 图层名layername=undefined则清空所有数据
   */
  clearDataLayer(layername) {
    let len = this.mapClass.layers.length;
    if (len === 0) {
      return;
    }
    if (layername === undefined) {
      switch (this.mapParams.mapType) {
        case MapType.Esri:
          for (let i = 0; i < len; i++) {
            this.mapClass.layers[i].layer.clear();
          }
          break;
        case MapType.Gaode:
          this.mapClass.map.clearMap();
          break;
        case MapType.GA:
          this.mapClass.map.clearOverlays();
          break;
        case MapType.Tianditu:
          for (let i = 0; i < len; i++) {
            this.mapClass.map.removeLayer(this.mapClass.layers[i].layer);
          }
          break;
      }
      this.mapClass.layers.splice(0, len);
    } else {
      let index = this.getLyrIndexByName(layername);
      if (index !== -1) {
        switch (this.mapParams.mapType) {
          case MapType.Esri:
            this.mapClass.layers[index].layer.clear();
            break;
          case MapType.Gaode:
            this.mapClass.map.remove(this.mapClass.layers[index].layer);
            break;
          case MapType.GA:
          case MapType.Tianditu:
            this.mapClass.map.removeLayer(this.mapClass.layers[index].layer);
            break;
        }
        this.mapClass.layers.splice(index, 1);
      }
    }
  }

  clearElement(layerName, index, element) {
    if (element !== undefined) {
      switch (this.mapParams.mapType) {
        case MapType.Esri:
          let lyr = this.getLyrByName(layerName);
          lyr.remove(element);
          break;
        case MapType.Gaode:
          this.mapClass.map.remove(element);
          break;
        case MapType.GA:
          this.mapClass.map.getOverlayLayer().removeOverlay(element);
          break;
        case MapType.Tianditu:
          this.mapClass.map.removeLayer(element);
          break;
      }
    }
  }

  /**
   * 根据图层名获取渲染数据图层
   * @param {string} lyrname 图层名
   */
  getLyrByName(lyrname) {
    for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
      if (this.mapClass.layers[i].name === lyrname) {
        return this.mapClass.layers[i].layer;
      }
    }
  }
  /**
   * 根据图层名关键字获取图层名
   * @param {string} key 关键字
   */
  getLyrFullName(key) {
    let fullNames = [];
    for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
      if (this.mapClass.layers[i].name.indexOf(key) !== -1) {
        fullNames.push(this.mapClass.layers[i].name);
      }
    }
    return fullNames;
  }
  /**
   * 获得可见图层名称
   * @param {Boolean} visible 可见性
   */
  getLayerNamebyVisibility(visible) {
    let layers = [];
    for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
      if (this.mapClass.layers[i].visible === visible) {
        layers.push(this.mapClass.layers[i].name);
      }
    }
    return layers;
  }
  /**
   * 设置图层可见性
   * @param {Boolean} visible  可见性
   * @param {string} layername 图层名
   */
  setLayerVisibility(visible, layername) {
    for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
      if (this.mapClass.layers[i].name === layername) {
        this.mapClass.layers[i].visible = visible;
        break;
      }
    }
  }

  /**
   * 新增数据图层
   * @param {*} layer  图层
   * @param {*} geoObj 数据
   */
  async insertDataIntoLayer(layer, geoObj) {
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        let [
          Point,
          Graphic,
          PictureMarkerSymbol,
          SpatialReference,
        ] = await esriLoader.loadModules([
          "esri/geometry/Point",
          "esri/graphic",
          "esri/symbols/PictureMarkerSymbol",
          "esri/SpatialReference",
        ]);
        for (let i = 0, len = geoObj.length; i < len; i++) {
          if (geoObj[i].longitude == null || geoObj[i].latitude == null)
            continue;
          if (geoObj[i].longitude === 0 || geoObj[i].latitude === 0) continue;
          let xCoor = geoObj[i].longitude;
          let yCoor = geoObj[i].latitude;
          let spatialRef = new SpatialReference({
            wkid: 4326,
          });
          let spatialRefName;
          if (this.mapParams.spatialReference) {
            spatialRefName = this.mapParams.spatialReference.name;
          }
          switch (spatialRefName) {
            case CoorSystem.sh_54:
              spatialRef = new SpatialReference(
                this.mapParams.spatialReference.content
              );
              break;
          }
          let pt = new Point(xCoor, yCoor, spatialRef);
          let marker = new Graphic(pt);
          marker.setAttributes(geoObj[i]);

          let picSymbol = new PictureMarkerSymbol(
            geoObj[i].mapPointStyle.baseUrl,
            geoObj[i].mapPointStyle.width,
            geoObj[i].mapPointStyle.height
          );
          marker.setSymbol(picSymbol);
          layer.add(marker);
        }

        break;
      case MapType.GA:
        for (let i = 0, len = geoObj.length; i < len; i++) {
          let pt = CoordsConvertUtil.wgs84ToGaode([
            [geoObj[i].longitude, geoObj[i].latitude],
          ]);

          let opts = new window.IMAP.MarkerOptions();
          opts.anchor = window.IMAP.Constants.BOTTOM_CENTER;
          opts.icon = new window.IMAP.Icon(geoObj[i].mapPointStyle.baseUrl, {
            size: new window.IMAP.Size(
              geoObj[i].mapPointStyle.width,
              geoObj[i].mapPointStyle.height
            ),
          });

          opts.editabled = false;
          opts.visible = true;
          let marker = new window.IMAP.Marker(
            new window.IMAP.LngLat(pt[0][0], pt[0][1]),
            opts
          );
          marker.D = geoObj[i];
          this.mapClass.map.getOverlayLayer().addOverlay(marker, true);
          layer.push(marker);
        }
        break;
      case MapType.Gaode:
        for (let i = 0, len = geoObj.length; i < len; i++) {
          let pt = CoordsConvertUtil.wgs84ToGaode([
            [geoObj[i].longitude, geoObj[i].latitude],
          ]);
          let content = `<div class="${geoObj[i].mapPointStyle.iconClass}"></div>`;
          let marker = new window.AMap.Marker({
            map: this.mapClass.map,
            position: [pt[0][0], pt[0][1]],
            extData: geoObj[i],
            content: content,
            offset: new window.AMap.Pixel(
              geoObj[i].mapPointStyle.xOffset,
              geoObj[i].mapPointStyle.yOffset
            ),
          });
          layer.push(marker);
        }
        break;
      case MapType.Tianditu:
        for (let i = 0, len = geoObj.length; i < len; i++) {
          let customIconDiv = window.L.divIcon({
            className: geoObj[i].mapPointStyle.iconClass,
            iconSize: [
              geoObj[i].mapPointStyle.width,
              geoObj[i].mapPointStyle.height,
            ],
          });
          let marker = window.L.marker(
            [geoObj[i].latitude, geoObj[i].longitude],
            {
              icon: customIconDiv,
              alt: geoObj[i],
            }
          );
          layer.addLayer(marker);
        }
        break;
    }
  }
  /**
   * 显示陌生人气泡
   * @param {Number} x x坐标
   * @param {Number} y y坐标
   * @param {string} inLoc 进入位置
   * @param {string} firstLoc 首次出现位置
   * @param {string} inTime 进入时间
   * @param {string} firstTime 首次出现时间
   * @param {Number} similarity 相似性
   * @param {string} inPic 进入抓拍图片
   * @param {string} firstPic 首次进入抓拍图片
   */
  showStranger(
    x,
    y,
    inLoc,
    firstLoc,
    inTime,
    firstTime,
    similarity,
    inPic,
    firstPic
  ) {
    let content;
    switch (this.mapParams.mapType) {
      case MapType.Esri:
      case MapType.GA:
        content =
          '<div class="map-bubbleStranger-esri"><h2>陌生人比对</h2><div class="map-capturePic"><div class="left"><div>' +
          '<div class="map-tv-1"><div><img class="map-BubbleImg" src="' +
          inPic +
          '" alt=""/></div></div></div><h3>实时抓拍</h3><p>' +
          inTime +
          "</p><p>" +
          inLoc +
          '</p></div><div class="middle"><span>' +
          similarity +
          "%</span></div>" +
          '<div class="right"><div><div class="map-tv-2"><div><img class="map-BubbleImg" src="' +
          firstPic +
          '" alt=""/></div></div></div><h3>首次出现</h3><p>' +
          firstTime +
          "</p><p>" +
          firstLoc +
          "</p></div></div></div>";
        break;
      case MapType.Gaode:
        content =
          '<div class="map-bubbleStranger-gd"><h2>陌生人比对</h2><div class="map-capturePic"><div class="left"><div>' +
          '<div class="map-tv-1"><div><img class="map-BubbleImg" src="' +
          inPic +
          '" alt=""/></div></div></div><h3>实时抓拍</h3><p>' +
          inTime +
          "</p><p>" +
          inLoc +
          '</p></div><div class="middle"><span>' +
          similarity +
          "%</span></div>" +
          '<div class="right"><div><div class="map-tv-2"><div><img class="map-BubbleImg" src="' +
          firstPic +
          '" alt=""/></div></div></div><h3>首次出现</h3><p>' +
          firstTime +
          "</p><p>" +
          firstLoc +
          '</p></div></div><div class="map-bubbleSharp"></div></div>';
        break;
      case MapType.Tianditu:
        content =
          '<div class="map-bubbleStranger-gd map-pop-mouse"><h2>陌生人比对</h2><div class="map-capturePic"><div class="left"><div>' +
          '<div class="map-tv-1"><div><img class="map-BubbleImg" src="' +
          inPic +
          '" alt=""/></div></div></div><h3>实时抓拍</h3><p>' +
          inTime +
          "</p><p>" +
          inLoc +
          '</p></div><div class="middle"><span>' +
          similarity +
          "%</span></div>" +
          '<div class="right"><div><div class="map-tv-2"><div><img class="map-BubbleImg" src="' +
          firstPic +
          '" alt=""/></div></div></div><h3>首次出现</h3><p>' +
          firstTime +
          "</p><p>" +
          firstLoc +
          '</p></div></div><div class="map-bubbleSharp"></div></div>';
        break;
    }

    return this.showPopup(x, y, content, 1);
  }
  /**
   * 显示视频气泡
   * @param {Number} x x坐标
   * @param {Number} y y坐标
   * @param {string} title 标题
   * @param {string} streamSource 视频链接
   */
  showVideo(x, y, title, streamSource) {
    let content;
    switch (this.mapParams.mapType) {
      case MapType.Esri:
      case MapType.GA:
        content =
          '<div class="map-bubbleVideo-esri"><h2>' +
          title +
          '</h2><div class="map-video"></div></div>';
        break;
      case MapType.Gaode:
        content =
          '<div class="map-bubbleVideo-gd"><h2>' +
          title +
          '</h2><div class="map-video"></div><div class="map-bubbleSharpVideo"></div></div>';
        break;
    }
    return this.showPopup(x, y, content, 2);
  }
  /**
   * 显示过车气泡
   * @param {Number} x x坐标
   * @param {Number} y y坐标
   * @param {string} dateTime 过车日期、时间
   * @param {string} loc 过车位置名称
   * @param {string} plate 车牌
   * @param {string} status 驶进/驶出
   * @param {string} pic 过车抓拍图片
   */
  showCar(x, y, dateTime, loc, plate, status, pic) {
    let content;
    switch (this.mapParams.mapType) {
      case MapType.Esri:
      case MapType.GA:
        content =
          '<div class="map-bubbleCar-esri"><div class="map-bubbleCar_m"><div class="map-tv"><div><img class="map-BubbleImg" src="' +
          pic +
          '" alt=""></div>' +
          '</div><div class="map-cotent"><p>' +
          dateTime +
          "</p><p>" +
          loc +
          "</p><p>" +
          plate +
          "</p><span>" +
          status +
          "</span></div>" +
          "</div></div>";
        break;
      case MapType.Gaode:
        content =
          '<div class="map-bubbleCar-gd"><div class="map-bubbleCar_m map-bubbleCar_m-gd"><div class="map-tv"><div><img class="map-BubbleImg" src="' +
          pic +
          '" alt=""></div>' +
          '</div><div class="map-cotent"><p>' +
          dateTime +
          "</p><p>" +
          loc +
          "</p><p>" +
          plate +
          "</p><span>" +
          status +
          "</span></div>" +
          '</div><div class="map-arrow"></div></div>';
        break;
      case MapType.Tianditu:
        content =
          '<div class="map-bubbleCar-gd map-pop-mouse"><div class="map-bubbleCar_m map-bubbleCar_m-gd"><div class="map-tv"><div><img class="map-BubbleImg" src="' +
          pic +
          '" alt=""></div>' +
          '</div><div class="map-cotent"><p>' +
          dateTime +
          "</p><p>" +
          loc +
          "</p><p>" +
          plate +
          "</p><span>" +
          status +
          "</span></div>" +
          '</div><div class="map-arrow"></div></div>';
        break;
    }

    return this.showPopup(x, y, content, 0);
  }
  /**
   * 关闭气泡
   */
  closePopup() {
    let tLayer = this.getLyrByName("popup");
    if (tLayer === undefined || tLayer.length === 0) {
      return;
    }
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        if (tLayer !== undefined) {
          for (let i = 0, len = tLayer.length; i < len; i++) {
            tLayer[i].destroy();
          }
        }
        break;
      case MapType.Gaode:
        // if (tLayer !== undefined) {
        //   this.mapClass.map.remove(tLayer)
        // }
        let one = [];
        one.push(tLayer[0]);
        this.mapClass.map.remove(one);
        tLayer.splice(0, 1);
        break;
      case MapType.GA:
        if (tLayer !== undefined) {
          this.mapClass.map.getOverlayLayer().clear(tLayer);
        }
        break;
      case MapType.Tianditu:
        if (tLayer !== undefined) {
          for (let i = 0, len = tLayer.length; i < len; i++) {
            this.mapClass.map.removeLayer(tLayer[i]);
          }
        }
        break;
    }
  }
  /**
   * 显示气泡
   * @param {Number} x x坐标
   * @param {Number} y y坐标
   * @param {string} content 内容 html 内容
   * @param {number} n 0-车辆气泡，1-陌生人气泡，2-视频气泡
   */
  async showPopup(x, y, content, n) {
    let glayer = this.getLyrByName("popup");
    if (glayer === undefined) {
      glayer = [];
      this.mapClass.layers.push(new MapOverLayer("popup", glayer, true));
    }
    switch (this.mapParams.mapType) {
      case MapType.Gaode:
        let xy = CoordsConvertUtil.wgs84ToGaode([[x, y]]);

        let marker = new window.AMap.Marker({
          position: [xy[0][0], xy[0][1]],
          content: content,
          draggable: false,
        });
        switch (n) {
          case 0:
            marker.setOffset(new window.AMap.Pixel(15, -100));
            break;
          case 1:
            marker.setOffset(new window.AMap.Pixel(10, -130));
            break;
          case 2:
            marker.setOffset(new window.AMap.Pixel(5, -205));
            break;
        }
        marker.setMap(this.mapClass.map);
        glayer.push(marker);
        break;
      case MapType.Esri:
        try {
          let [
            EsriPopup,
            domConstruct,
            domClass,
            Point,
            SpatialReference,
            InfoWindow,
          ] = await esriLoader.loadModules([
            "esri/dijit/Popup",
            "dojo/dom-construct",
            "dojo/dom-class",
            "esri/geometry/Point",
            "esri/SpatialReference",
            "esri/dijit/InfoWindow",
          ]);
          let popTip = new EsriPopup(
            {
              anchor: "auto",
            },
            domConstruct.create("div")
          );
          popTip.startup();
          popTip.setContent(content);
          popTip.setMap(this.mapClass.map);
          let spatialRef = new SpatialReference({
            wkid: 4326,
          });
          let xCoor = x;
          let yCoor = y;
          let spatialRefName;
          if (this.mapParams.spatialReference) {
            spatialRefName = this.mapParams.spatialReference.name;
          }
          switch (spatialRefName) {
            case CoorSystem.sh_54:
              spatialRef = new SpatialReference(
                this.mapParams.spatialReference.content
              );
              break;
          }
          popTip.show(new Point(xCoor, yCoor, spatialRef));
          glayer.push(popTip);
        } catch (error) {
          console.log(error);
        }
        break;
      case MapType.GA:
        let pt = CoordsConvertUtil.wgs84ToGaode([[x, y]]);
        let infowindow = new window.IMAP.InfoWindow("", {
          offset: new window.IMAP.Pixel(0, 0),
          position: new window.IMAP.LngLat(pt[0][0], pt[0][1]),
          visible: true,
        });
        infowindow.setContent(content);
        this.mapClass.map.getOverlayLayer().addOverlay(infowindow);

        glayer.push(infowindow);
        break;
      case MapType.Tianditu:
        let offset = [0, 85];
        switch (n) {
          case 0:
            offset = [0, 85];
            break;
          case 1:
            offset = [-8, 118];
            break;
        }
        let markerTip = window.L.marker([y, x], {
          icon: window.L.divIcon({
            className: "leaflet-pulse-icon",
            html: content,
            iconAnchor: offset,
          }),
        }).addTo(this.mapClass.map);
        glayer.push(markerTip);
        break;
    }
  }
  /**
   * 打开popup信息窗方法
   */
  async showName(evt) {
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        let [
          GraphicsLayer,
          Graphic,
          TextSymbol,
        ] = await esriLoader.loadModules([
          "esri/layers/GraphicsLayer",
          "esri/graphic",
          "esri/symbols/TextSymbol",
        ]);
        let tLayer = this.getLyrByName("label");
        if (tLayer === undefined) {
          tLayer = new GraphicsLayer();
          this.mapClass.map.addLayer(tLayer);
          this.mapClass.layers.push(new MapOverLayer("label", tLayer, true));
        }
        let tSym = new TextSymbol({
          type: "esriTS",
          color: [255, 255, 255, 255],
          backgroundColor: [255, 0, 0, 255],
          verticalAlignment: "top",
          horizontalAlignment: "left",
          angle: 0,
          xoffset: 5,
          yoffset: 0,
          font: {
            family: "Arial",
            size: 14,
            style: "normal",
            decoration: "none",
          },
        });

        let markerTxt = new Graphic(evt.mapPoint, tSym);
        tSym.setText(
          evt.graphic.attributes === undefined
            ? ""
            : evt.graphic.attributes.name
        );
        tLayer.add(markerTxt);
        break;
    }
  }
  /**
   * 关闭popup信息窗方法
   */
  hideName(evt) {
    switch (this.mapParams.mapType) {
      // case MapType.Gaode:
      //   this.mapClass.map.clearInfoWindow()
      //   break
      case MapType.Esri:
        // if (tooltip !== undefined) tooltip.hide()
        let tLayer = this.getLyrByName("label");
        this.mapClass.map.removeLayer(tLayer);
        let index = this.getLyrIndexByName("label");
        this.mapClass.layers.splice(index, 1);
        break;
    }
  }
  /**
   * 设置回地图显示范围
   * @param {} extObj ext = {center: [0, 0], zoom: 0, rotation: 0, pitch: 0, xmin: 0, ymin: 0, xmax: 0, ymax: 0}
   */
  async setbackExtent(extObj) {
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        let [Extent] = await esriLoader.loadModules(["esri/geometry/Extent"]);
        this.mapClass.map.setExtent(
          new Extent(
            {
              xmin: extObj.xmin,
              ymin: extObj.ymin,
              xmax: extObj.xmax,
              ymax: extObj.ymax,
            },
            true
          )
        );
        break;
      case MapType.Gaode:
        this.mapClass.map.setCenter(extObj.center);
        this.mapClass.map.setZoom(extObj.zoom);
        this.mapClass.map.setRotation(extObj.rotation);
        this.mapClass.map.setPitch(extObj.pitch);
        break;
      case MapType.GA:
        this.mapClass.map.setCenter(extObj.center, extObj.zoom);
        break;
      case MapType.Tianditu:
        let latlng = window.L.latLng(extObj.center[1], extObj.center[0]);
        this.mapClass.map.setView(latlng);
        this.mapClass.map.invalidateSize();
        break;
    }
  }
  /**
   * 居中缩放地图
   * @param {Number} x 中心点x坐标
   * @param {Number} y 中心点y坐标
   * @param {Number} zoomlevel 缩放级别
   */
  async setCenterAndZoom(x, y, zoomlevel) {
    if (this.mapClass.map == null) {
      return;
    }
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        let [Point, SpatialReference] = await esriLoader.loadModules([
          "esri/geometry/Point",
          "esri/SpatialReference",
        ]);

        let xCoor = x;
        let yCoor = y;
        let spatialRef = new SpatialReference({
          wkid: 4326,
        });
        let spatialRefName;
        if (this.mapParams.spatialReference) {
          spatialRefName = this.mapParams.spatialReference.name;
        }
        switch (spatialRefName) {
          case CoorSystem.sh_54:
            spatialRef = new SpatialReference(
              this.mapParams.spatialReference.content
            );
            break;
        }
        this.mapClass.map.centerAndZoom(
          new Point(xCoor, yCoor, spatialRef),
          zoomlevel
        );

        break;
      case MapType.Gaode:
        let xy = CoordsConvertUtil.wgs84ToGaode([[x, y]]);
        let center = new window.AMap.LngLat(xy[0][0], xy[0][1]);
        this.mapClass.map.setZoomAndCenter(zoomlevel, center);

        if (this.mapParams.viewMode === "3D") {
          this.mapClass.map.setRotation(0);
          this.mapClass.map.setPitch(this.mapParams.pitch);
        }
        break;
      case MapType.GA:
        let pt = CoordsConvertUtil.wgs84ToGaode([[x, y]]);
        let centerPt = new window.IMAP.LngLat(pt[0][0], pt[0][1]);
        this.mapClass.map.setCenter(centerPt, zoomlevel);
        break;
      case MapType.Tianditu:
        let latlng = window.L.latLng(y, x);
        this.mapClass.map.setView(latlng, zoomlevel);
        this.mapClass.map.invalidateSize();
        break;
    }
  }
  /**
   * 地图移至范围
   * @param {number} xmin
   * @param {number} ymin
   * @param {number} xmax
   * @param {number} ymax
   */
  async setExtent(xmin, ymin, xmax, ymax) {
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        let [Extent] = await esriLoader.loadModules(["esri/geometry/Extent"]);
        let sExtent = new Extent({
          xmin: xmin,
          ymin: ymin,
          xmax: xmax,
          ymax: ymax,
        });
        this.mapClass.map.setExtent(sExtent, true);
        break;
      case MapType.Gaode:
        let minMax = CoordsConvertUtil.wgs84ToGaode([
          [xmin, ymin],
          [xmax, ymax],
        ]);
        let center = new window.AMap.LngLat(
          (minMax[0][0] + minMax[1][0]) / 2,
          (minMax[0][1] + minMax[1][1]) / 2
        );
        this.mapClass.map.setZoomAndCenter(this.mapParams.zoom, center);
        break;
      case MapType.GA:
        let pt = CoordsConvertUtil.wgs84ToGaode([
          [xmin, ymin],
          [xmax, ymax],
        ]);
        this.mapClass.map.setCenter(
          new window.IMAP.LngLat(
            (pt[0][0] + pt[1][0]) / 2,
            (pt[0][1] + pt[1][1]) / 2
          )
        );
        break;
      case MapType.Tianditu:
        let latlng = window.L.latLng((ymin + ymax) / 2, (xmin + xmax) / 2);
        this.mapClass.map.setView(latlng, this.mapParams.zoom);
        this.mapClass.map.invalidateSize();
        break;
    }
  }
  /**
   * 隐藏指定图层
   * @param {string} layername 图层名
   */
  hideLayer(layername) {
    let renderlayer = this.getLyrByName(layername);
    if (renderlayer === undefined) {
      return;
    }
    switch (this.mapParams.mapType) {
      case MapType.Gaode:
        for (let i = 0, len = renderlayer.length; i < len; i++) {
          renderlayer[i].setMap(null);
        }
        break;
      case MapType.Esri:
        renderlayer.hide();
        break;
      case MapType.GA:
        for (let i = 0, len = renderlayer.length; i < len; i++) {
          renderlayer[i].visible(false);
        }
        break;
      case MapType.Tianditu:
        this.mapClass.map.removeLayer(renderlayer);
        break;
    }
  }
  /**
   * 显示指定图层
   * @param {string} layername 图层名
   */
  showLayer(layername) {
    let renderlayer = this.getLyrByName(layername);
    if (renderlayer === undefined) {
      return false;
    } else {
      switch (this.mapParams.mapType) {
        case MapType.Gaode:
          for (let i = 0, len = renderlayer.length; i < len; i++) {
            renderlayer[i].setMap(this.mapClass.map);
          }
          break;
        case MapType.Esri:
          renderlayer.show();
          break;
        case MapType.GA:
          for (let i = 0, len = renderlayer.length; i < len; i++) {
            renderlayer[i].visible(true);
          }
          break;
        case MapType.Tianditu:
          this.mapClass.map.addLayer(renderlayer);
      }
      return true;
    }
  }

  /**
   * 获取所有layerNames
   * @returns []
   */
  getLayerNames() {
    if (
      this.mapClass.layerDatas == null ||
      this.mapClass.layerDatas.length == 0
    ) {
      return [];
    }

    return this.mapClass.layerDatas.map((x) => x.layername);
  }

  showLayerAtMaxZoom() {
    let visibleLayers = this.getLayerNamebyVisibility(true);
    if (this.mapClass.map.getZoom() === this.mapParams.zooms[1]) {
      for (let i = 0, len = visibleLayers.length; i < len; i++) {
        this.showLayer(visibleLayers[i]);
      }
    } else {
      for (let i = 0, len = visibleLayers.length; i < len; i++) {
        if (visibleLayers[i].indexOf("_label") > -1) {
          this.hideLayer(visibleLayers[i]);
        }
      }
    }
  }
  /**
   * 开始闪烁动画
   * @param {*} x
   * @param {*} y
   * @param {*} xoffset
   * @param {*} yoffset
   * @param {*} blinkUrl 闪烁动画图片 gif
   */
  async startBlinkingObj(x, y, xoffset, yoffset, blinkUrl) {
    if (this.mapParams.mapType === MapType.Esri) {
      let [
        GraphicsLayer,
        Graphic,
        Point,
        PictureMarkerSymbol,
        SpatialReference,
      ] = await esriLoader.loadModules([
        "esri/layers/GraphicsLayer",
        "esri/graphic",
        "esri/geometry/Point",
        "esri/symbols/PictureMarkerSymbol",
        "esri/SpatialReference",
      ]);

      // create alarm layer if it doesn't exist
      let glayer = this.getLyrByName("alarm");
      if (glayer === undefined) {
        glayer = new GraphicsLayer();
        this.mapClass.map.addLayer(glayer, 0);
        this.mapClass.layers.push(new MapOverLayer("alarm", glayer, true));
      }
      this.setLayerVisibility(true, "alarm");
      let symbol = new PictureMarkerSymbol(blinkUrl, 64, 64);
      let spatialRef = new SpatialReference({
        wkid: 4326,
      });
      let xCoor = x;
      let yCoor = y;
      let spatialRefName;
      if (this.mapParams.spatialReference) {
        spatialRefName = this.mapParams.spatialReference.name;
      }
      switch (spatialRefName) {
        case CoorSystem.sh_54:
          spatialRef = new SpatialReference(
            this.mapParams.spatialReference.content
          );
          break;
      }
      let pt = new Point(xCoor, yCoor, spatialRef);
      let graphicFlash = new Graphic(pt, symbol);
      glayer.add(graphicFlash);
      return graphicFlash;
    } else if (this.mapParams.mapType === MapType.Gaode) {
      let xy = CoordsConvertUtil.wgs84ToGaode([[x, y]]);
      let gdXY = new window.AMap.LngLat(xy[0][0], xy[0][1]);

      let glayer = this.getLyrByName("alarm");
      if (glayer === undefined) {
        glayer = [];
        this.mapClass.layers.push(new MapOverLayer("alarm", glayer, true));
      }
      this.setLayerVisibility(true, "alarm");
      let markerBlinking = new window.AMap.Marker({
        position: gdXY,
        content: '<em class="wave"></em>',
        zIndex: 9999,
        offset: new window.AMap.Pixel(xoffset, yoffset),
      });
      markerBlinking.setMap(this.mapClass.map);
      glayer.push(markerBlinking);

      return markerBlinking;
    } else if (this.mapParams.mapType === MapType.GA) {
      let xy = CoordsConvertUtil.wgs84ToGaode([[x, y]]);

      let glayer = this.getLyrByName("alarm");
      if (glayer === undefined) {
        glayer = [];
        this.mapClass.layers.push(new MapOverLayer("alarm", glayer, true));
      }
      this.setLayerVisibility(true, "alarm");
      let opts = new window.IMAP.MarkerOptions();
      opts.anchor = window.IMAP.Constants.BOTTOM_CENTER;
      opts.icon = new window.IMAP.Icon(blinkUrl, {
        size: new window.IMAP.Size(18, 18),
      });

      opts.editabled = false;
      opts.visible = true;
      let marker = new window.IMAP.Marker(
        new window.IMAP.LngLat(xy[0][0], xy[0][1]),
        opts
      );
      this.mapClass.map.getOverlayLayer().addOverlay(marker, true);
      glayer.push(marker);
      return marker;
    } else if (this.mapParams.mapType === MapType.Tianditu) {
      let glayer = this.getLyrByName("alarm");
      if (glayer === undefined) {
        glayer = window.L.layerGroup();
        this.mapClass.layers.push(new MapOverLayer("alarm", glayer, true));
      }
      this.setLayerVisibility(true, "alarm");
      let pulseDiv = window.L.divIcon({
        className: "leaflet-pulse-icon",
        html: '<div class="pulse"></div>',
        // html:'<em class="wave"></em>',
        iconAnchor: [15, 15],
      });

      let markerBlinking = window.L.marker([y, x], {
        icon: pulseDiv,
        zIndexOffset: -1,
      });
      glayer.addLayer(markerBlinking);

      return markerBlinking;
    }
  }
  /**
   * 关闭闪烁动画
   * @param {*} blinking
   */
  stopBlinkingObj(blinking) {
    let lyr = this.getLyrByName("alarm");
    if (lyr === undefined) {
      return;
    }
    if (blinking === undefined) {
      switch (this.mapParams.mapType) {
        case MapType.Esri:
        case MapType.GA:
          this.mapClass.map.removeLayer(lyr);
          break;
        case MapType.Gaode:
          this.mapClass.map.remove(lyr);
          break;
        case MapType.Tianditu:
          this.mapClass.map.removeLayer(lyr);
          break;
      }
      let index = getLyrIndexByName("alarm");
      this.mapClass.layers.splice(index, 1);
    } else {
      switch (this.mapParams.mapType) {
        case MapType.Esri:
          lyr.remove(blinking);
          break;
        case MapType.Gaode:
          this.mapClass.map.remove(blinking);
          break;
        case MapType.GA:
          this.mapClass.map.getOverlayLayer().removeOverlay(blinking);
          break;
        case MapType.Tianditu:
          this.mapClass.map.removeLayer(blinking);
          break;
      }
    }
    this.setLayerVisibility(false, "alarm");
  }

  /**
   * 指定图层里查找距离中心点一定距离要素
   * @param {*} layername
   * @param {*} distance
   * @param {*} centerX
   * @param {*} centerY
   */
  searchNearbyObj(layername, distance, centerX, centerY) {
    let lyr = this.getLyrByName(layername);
    let results = [];
    if (lyr !== undefined) {
      // Esri
      if (this.mapParams.mapType === MapType.Esri) {
        let centerPt = CoordsConvertUtil.lonLatToMercator([centerX, centerY]);
        for (let i = 0, len = lyr.graphics.length; i < len; i++) {
          let g = lyr.graphics[i];
          let pt = CoordsConvertUtil.lonLatToMercator(g.geometry);
          let dis = this.getEuclideanDistance(centerPt, pt);
          if (dis < distance) {
            results.push(g);
          }
        }
      }

      // Gaode
      if (this.mapParams.mapType === MapType.Gaode) {
        let lnglat1 = new window.AMap.LngLat(centerX, centerY);
        for (let i = 0, len = lyr.length; i < len; i++) {
          let pos = lyr[i].getPosition();
          let dis = lnglat1.distance(pos);

          if (dis < distance) {
            results.push(lyr[i]);
          }
        }
      }

      // GA
      if (this.mapParams.mapType === MapType.GA) {
        let lnglat1 = new window.IMap.LngLat(centerX, centerY);
        for (let i = 0, len = lyr.length; i < len; i++) {
          let pos = lyr[i].getPosition();
          let dis = lnglat1.distance(pos);

          if (dis < distance) {
            results.push(lyr[i]);
          }
        }
      }

      // Tianditu
      if (this.mapParams.mapType === MapType.Tianditu) {
        let lnglat1 = window.L.latLng(centerX, centerY);
        let markers = lyr.getLayers();
        for (let i = 0, len = markers.length; i < len; i++) {
          let dis = lnglat1.distanceTo(markers[i].getLatLng());

          if (dis < distance) {
            results.push(markers[i]);
          }
        }
      }
    }
    return results;
  }
  /**
   * 计算两点之间欧几里何距离
   * @param {*} pt1
   * @param {*} pt2
   */
  getEuclideanDistance(pt1, pt2) {
    let dis = Math.sqrt(
      Math.pow(pt1[0] - pt2[0], 2) + Math.pow(pt1[1] - pt2[1], 2)
    );
    return dis;
  }

  /**
   * 计算两点间实际距离，返回距离，单位:米
   * @param {Array} pt1 [x,y]
   * @param {Array} pt2 [x,y]
   */
  getRealDistance(pt1, pt2) {
    return this.getEuclideanDistance(
      CoordsConvertUtil.lonLatToMercator(pt1),
      CoordsConvertUtil.lonLatToMercator(pt2)
    );
  }

  /**
   * 地图图层点击事件
   * @param {*} layername 图层名
   * @param {*} callbackEvent 回调事件
   */
  onLayerClick(layername, callbackEvent) {
    if (layername === undefined) {
      for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
        if (this.mapParams.mapType === MapType.Esri) {
          this.mapClass.layers[i].layer.on("click", function(e) {
            callbackEvent(e);
          });
        } else if (this.mapParams.mapType === MapType.Gaode) {
          for (
            let j = 0, len = this.mapClass.layers[i].layer.length;
            j < len;
            j++
          ) {
            this.mapClass.layers[i].layer[j].on("click", function(e) {
              callbackEvent(e);
            });
          }
        }
      }
    } else {
      let lyr = this.getLyrByName(layername);
      if (this.mapParams.mapType === MapType.Esri) {
        lyr.on("click", function(e) {
          callbackEvent(e);
        });
      } else if (this.mapParams.mapType === MapType.Gaode) {
        for (let j = 0, len = lyr.length; j < len; j++) {
          lyr[j].on("click", function(e) {
            callbackEvent(e);
          });
        }
      }
    }
  }

  onClick(callbackEvent) {
    this.mapClass.map.on("click", function(e) {
      callbackEvent(e);
    });
  }

  /**
   * 地图范围改变触发
   * @param {*} callbackEvent
   * @returns
   */
  onExtentChange(callbackEvent) {
    if (this.mapClass.map == null) {
      return;
    }
    switch (this.mapParams.mapType) {
      // case MapType.Gaode:
      //   this.mapClass.map.on('dragend', function (e) {
      //     callbackEvent(e)
      //   })
      //   this.mapClass.map.on('resize', function (e) {
      //     callbackEvent(e)
      //   })
      //   this.mapClass.map.on('zoomchange', function (e) {
      //     callbackEvent(e)
      //   })
      //   break

      // case 'BD':
      //   this.mapClass.map.addEventListener('zoomend', callbackEvent)
      //   this.mapClass.map.addEventListener('dragend', callbackEvent)
      //   this.mapClass.map.addEventListener('resize', callbackEvent)
      //   break

      case MapType.Esri:
        if (this.mapClass.map == null) {
          return;
        }
        this.mapClass.map.on("extent-change", function(e) {
          callbackEvent(e);
        });
        break;
    }
  }

  /**
   * 鼠标移入图层
   * @param {*} layername
   * @param {*} callbackEvent
   */
  onLayerMouseOver(layername, callbackEvent) {
    let event = "mouseover";
    if (this.mapParams.mapType === MapType.Esri) {
      event = "mouse-over";
    }
    if (layername === undefined) {
      for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
        this.mapClass.layers[i].layer.on(event, function(e) {
          callbackEvent(e);
        });
      }
    } else {
      if (this.mapParams.mapType === MapType.Gaode) {
        let markerlist = this.getLyrByName(layername);
        console.log(this.mapClass.layers);
        markerlist.forEach((x) => {
          x.on(event, function(e) {
            callbackEvent(e);
          });
        });
        return;
      }

      let lyr = this.getLyrByName(layername);
      lyr.on(event, function(e) {
        callbackEvent(e);
      });
    }
  }

  /**
   * 鼠标移出图层
   * @param {*} layername
   * @param {*} callbackEvent
   */
  onLayerMouseOut(layername, callbackEvent) {
    let event = "mouseout";
    if (this.mapParams.mapType === MapType.Esri) {
      event = "mouse-out";
    }
    if (layername === undefined) {
      for (let i = 0, len = this.mapClass.layers.length; i < len; i++) {
        this.mapClass.layers[i].layer.on(event, function(e) {
          callbackEvent(e);
        });
      }
    } else {
      if (this.mapParams.mapType === MapType.Gaode) {
        let markerlist = this.getLyrByName(layername);
        markerlist.forEach((x) => {
          x.on(event, function(e) {
            callbackEvent(e);
          });
        });
        return;
      }

      let lyr = this.getLyrByName(layername);
      lyr.on(event, function(e) {
        callbackEvent(e);
      });
    }
  }

  /**
   * 获取地图范围（3维地图获取中心点、角度等）
   * @returns
   */
  getMapExtent() {
    let ext = {
      center: [0, 0],
      zoom: 0,
      rotation: 0,
      pitch: 0,
      xmin: 0,
      ymin: 0,
      xmax: 0,
      ymax: 0,
    };
    switch (this.mapParams.mapType) {
      case MapType.Esri:
        ext.xmin = this.mapClass.map.extent.xmin;
        ext.ymin = this.mapClass.map.extent.ymin;
        ext.xmax = this.mapClass.map.extent.xmax;
        ext.ymax = this.mapClass.map.extent.ymax;
        break;
      case MapType.Gaode:
        ext.center = [
          this.mapClass.map.getCenter().lng,
          this.mapClass.map.getCenter().lat,
        ];
        ext.zoom = this.mapClass.map.getZoom();
        ext.rotation = this.mapClass.map.getRotation();
        ext.pitch = this.mapClass.map.getPitch();
        break;
      case MapType.GA:
      case MapType.Tianditu:
        ext.center = [
          this.mapClass.map.getCenter().lng,
          this.mapClass.map.getCenter().lat,
        ];
        ext.zoom = this.mapClass.map.getZoom();
        break;
    }

    return ext;
  }

  /**
   * 获得地图缩放级别
   */
  getMapZoom() {
    return this.mapClass.map.getZoom();
  }

  /**
   * 获取地图mapExtent参数
   * @returns
   */
  getDataExtent() {
    return this.mapClass.mapExtent;
  }

  /**
   * 显示图层及其文字标注
   * @param {*} layername 图层名
   * @param {*} isClickable 是否可点击
   * @param {*} isOnTop 是否OnTop
   */
  showLayerAndLabel(layername, isClickable, isOnTop) {
    let dataList = this.mapClass.layerDatas.filter(
      (x) => x.layername === layername
    );
    let isLabel = false;
    if (!isOnTop) {
      if (!showLayer(layername)) {
        addPointsLayer(layername, dataList, isLabel, isClickable);
      }
    } else {
      this.clearDataLayer(layername);
      this.clearDataLayer(layername + "_label");
      addPointsLayer(layername, dataList, isLabel, isClickable);
    }
    this.setLayerVisibility(true, layername + "_label");
    this.setLayerVisibility(true, layername);
  }
  // 隐藏图层及其文字标注
  hideLayerAndLabel(layername) {
    this.hideLayer(layername);
    this.setLayerVisibility(false, layername + "_label");
    this.setLayerVisibility(false, layername);
  }
  // id
  showLocation(layername, isClickable) {
    let dataList = this.mapClass.layerDatas.filter(
      (x) => x.layername === layername
    );
    let tLayer = this.getLyrByName(layername);
    if (tLayer === undefined) {
      this.addPointsLayer(layername, dataList, false, isClickable);
    } else {
      this.insertDataIntoLayer(tLayer, dataList);
    }
  }
  addClusterListenZoom(){
    let _that=this
    this.mapClass.map.on("zoomend", function() {     
      let mapZoom=_that.getMapZoom();
      console.log('mapZoom',mapZoom)
      if(mapZoom<13){
        _that.clearCluster()
        _that.addCluster('310104011028001_fence_line','七星岗街道')
      }else if(mapZoom>=13&&mapZoom<16){
        _that.clearCluster()
        _that.addCluster('310104011028001_fence_line','田林十二村')
      }else{
        // 什么都不聚合
      }

    });
  }
  addCluster(layername, clusterViewName) {
    let _that = this;
    if (this.mapParams.mapType === MapType.Gaode) {
      if (this.cluster) {
        this.cluster.setMap(null);
      }

      // let markerlist =[]
      // for (let index = 0; index < this.mapClass.layers.length; index++) {
      //   markerlist=markerlist.concat(this.mapClass.layers[index].layer)
      // }
      // console.log(markerlist)
      let markerlist = this.getLyrByName(layername);
      window.AMap.plugin(["AMap.MarkerClusterer"], function() {
        _that.cluster = new window.AMap.MarkerClusterer(
          _that.mapClass.map,
          markerlist,
          {
            gridSize: 80,
            minClusterSize: 10,
            maxZoom: 16,
            renderClusterMarker: function(context) {
              var factor = Math.pow(context.count / markerlist.length, 1 / 18);
              var div = document.createElement("div");

              var size = Math.round(
                30 + Math.pow(context.count / markerlist.length, 1 / 5) * 20
              );
              div.style.width = div.style.height = size + "px";
              // context.marker.getExtData()
              div.innerHTML = `<div style="width: 120px;height: 120px;background: rgba(99, 194, 255, 0.5);border: 4px solid #63C2FF;border-radius: 50%;display: flex;justify-content: center;align-items: center;backdrop-filter: blur(5px);">
              <div>
                  <div style="font-size:16px;color: #F2FCFF;font-weight: 800;line-height: 22px;">
                      ${clusterViewName}
                  </div>
                  <div style="font-size:14px;color: #43F3F4;margin-top: 6px;line-height: 20px;">
                      ${context.count}个设备
                  </div>
              </div>
          </div>`;

              context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
              context.marker.setContent(div);
            },
          }
        );
      });
      return;
    }
  }

  clearCluster() {
    if (this.mapParams.mapType === MapType.Gaode) {
      if (this.cluster) {
        this.cluster.setMap(null);
      }
    }
  }
}
