    import { SpatialReference, Point } from '../../../base/geometry'
    import { Log } from '../../../util'
    import LOD from './LOD'
    import TileInfo from './TileInfo'
    import { LayerType } from '../../../base/enum'
    import { Projection } from '../../../base'
    /**
     * @description: 瓦片解析工具
     * @return {*}
     */
    export default class TileInfoUtil {
      /**
       * @description: 解析igs1.0 tileInfo
       * @param {Object} tileInfo
       * @return {TileInfo}
       */
      static parseTileInfo1(tileInfo) {
        if (!tileInfo) {
          Log.error('tileInfo未定义')
        }
        const { tileWidth, tileHeight, lods, originX, originY } = tileInfo
        return new TileInfo({
          origin: new Point({
            coordinates: [originX, originY]
          }),
          lods: lods.map((lod) => {
            return LOD.fromJSON(lod)
          }),
          size: [tileWidth, tileHeight]
        })
        // igs1.0 tileInfo
        // {
        //   name: 'EPSG_4326_WORLD_TILE',
        //   type: 'tile',
        //   xMin: -180,
        //   xMax: 180,
        //   yMin: -90,
        //   yMax: 90,
        //   tileWidth: 256,
        //   tileHeight: 256,
        //   startLevel: 0,
        //   endLevel: 9,
        //   resolutions: [
        //     0.7031249999891483, 0.3515624999945742, 0.1757812499972871,
        //     0.08789062499864354, 0.04394531249932177, 0.021972656249660886,
        //     0.010986328124830443, 0.005493164062415209, 0.0027465820312076047,
        //     0.001373291015603805
        //   ],
        //   lods: [
        //     {
        //       level: 0,
        //       resolution: 0.7031249999891483,
        //       scale: 295829355.45,
        //       dxTileLogic: 179.99999999722198,
        //       dyTileLogic: 179.99999999722198,
        //       tileLogicRect: {
        //         xmin: -180,
        //         ymin: -89.99999999722198,
        //         xmax: 179.99999999444395,
        //         ymax: 90
        //       }
        //     },
        //     {
        //       level: 1,
        //       resolution: 0.3515624999945742,
        //       scale: 147914677.725,
        //       dxTileLogic: 89.99999999861099,
        //       dyTileLogic: 89.99999999861099,
        //       tileLogicRect: {
        //         xmin: -180,
        //         ymin: -89.99999999722198,
        //         xmax: 179.99999999444395,
        //         ymax: 90
        //       }
        //     }
        //   ],
        //   originX: -180,
        //   originY: 90,
        //   originType: 'LeftTop'
        // }
      }

      /**
       * @description: 解析igs2.0 tileInfo
       * @param {Object} tileInfo
       * @return {TileInfo}
       */
      static parseTileInfo2(tileInfo) {
        if (!tileInfo) {
          Log.error('tileInfo未定义')
        }

        const { cols, rows, dpi, format, origin, lods, spatialReference } = tileInfo

        return new TileInfo({
          dpi,
          format,
          origin: new Point({
            coordinates: [origin.x, origin.y],
            spatialReference: new SpatialReference(spatialReference)
          }),
          lods: lods.map((lod) => {
            return LOD.fromJSON(lod)
          }),
          size: [cols, rows],
          spatialReference: new SpatialReference(spatialReference)
        })
        // igs2.0 tileInfo
        //  {
        //   endLevel: 14,
        //   startLevel: 0,
        //   cols: 256,
        //   rows: 256,
        //   compressionQuality: null,
        //   dpi: 0,
        //   format: 'PNG',
        //   origin: {
        //     x: -5123200,
        //     y: 10002100
        //   },
        //   lods: [
        //     {
        //       level: 0,
        //       resolution: 156367.47632692187,
        //       scale: 590995186.1175
        //     },
        //     {
        //       level: 1,
        //       resolution: 78183.73816346093,
        //       scale: 295497593.05875
        //     }
        //   ],
        //   spatialReference: {
        //     wkid: 4547,
        //     name: '高斯大地坐标系_中国2000_38带3_北'
        //   }
        // }
      }

      /**
       * @description: 解析arcgis tileInfo
       * @param {Object} tileInfo
       * @return {TileInfo}
       */
      static parseArcgisTileInfo(tileInfo) {
        if (!tileInfo) {
          Log.error('tileInfo未定义')
        }
        const { cols, rows, dpi, format, origin, lods, spatialReference } = tileInfo
        return new TileInfo({
          dpi,
          format,
          origin: new Point({
            coordinates: [origin.x, origin.y],
            spatialReference: new SpatialReference({
              wkid: spatialReference.latestWkid || spatialReference.wkid
            })
          }),
          lods: lods.map((lod) => {
            return LOD.fromJSON(lod)
          }),
          size: [cols, rows],
          spatialReference: new SpatialReference({
            wkid: spatialReference.latestWkid || spatialReference.wkid
          })
        })
        //  arcgis tileInfo
        // {
        //   rows: 256,
        //   cols: 256,
        //   dpi: 96,
        //   format: 'JPEG',
        //   compressionQuality: 90,
        //   origin: {
        //     x: -20037508.342787,
        //     y: 20037508.342787
        //   },
        //   spatialReference: {
        //     wkid: 102100,
        //     latestWkid: 3857
        //   },
        //   lods: [
        //     {
        //       level: 0,
        //       resolution: 156543.03392800014,
        //       scale: 591657527.591555
        //     },
        //     {
        //       level: 1,
        //       resolution: 78271.51696399994,
        //       scale: 295828763.795777
        //     }
        //   ]
        // }
      }

      /**
       * @description: WMS tileInfo
       * @param {WMSLayer} layer
       * @return {TileInfo}
       */
      static parseWMSTileInfo(layer) {
        if (!layer) {
          Log.error('wmsLayer未定义')
        }
        // 处理wms 图层
        const extent = layer.extent
        const tileSize = Math.max(layer.imageWidth, layer.imageHeight)
        const resolution0 =
          Math.max(extent.ymax - extent.ymin, extent.xmax - extent.xmin) / tileSize
        const resolutions = []
        resolutions.push(resolution0)
        for (let r = 0; r < 20; r++) {
          resolutions.push(resolutions[r] / 2)
        }

        const origin = new Point({
          coordinates: [extent.xmin, extent.ymax],
          spatialReference: layer.spatialReferences[0]
        })

        return new TileInfo({
          origin,
          lods: resolutions.map((resolution, index) => {
            return LOD.fromJSON({
              level: index,
              resolution,
              scale: (resolution * 96) / 0.0254
            })
          }),
          size: [layer.imageWidth, layer.imageHeight],
          spatialReference: layer.spatialReferences[0]
        })
      }

      /**
       * @description: MapImage tileInfo
       * @param {IGSMapImageLayer} layer
       * @return {TileInfo}
       */
      static parseMapImageTileInfo(layer, extent) {
        if (!layer) {
          Log.error('IGSMapImageLayer未定义')
        }
        // 处理wms 图层
        extent = extent || layer.extent
        let tileWidth = 256
        let tileHeight = 256
        // 对于igsMapImage layer图层，如果是瓦片渲染模式，
        // 则tileSize取imageWidth/imageHeight（后续该参数名称改为tileWidth/tileHeight）。
        // 否则tileSize为默认值。
        if (layer.type === LayerType.igsMapImage && layer.renderMode === 'tile') {
          tileWidth = layer.imageWidth
          tileHeight = layer.imageHeight
        }
        const tileSize = Math.max(tileWidth, tileHeight)
        const resolution0 =
          Math.max(extent.ymax - extent.ymin, extent.xmax - extent.xmin) / tileSize
        const resolutions = []
        resolutions.push(resolution0)
        for (let r = 0; r < 20; r++) {
          resolutions.push(resolutions[r] / 2)
        }

        const origin = new Point({
          coordinates: [extent.xmin, extent.ymax],
          spatialReference: layer.spatialReference
        })
        return new TileInfo({
          origin,
          lods: resolutions.map((resolution, index) => {
            return LOD.fromJSON({
              level: index,
              resolution,
              scale: (resolution * 96) / 0.0254
            })
          }),
          size: [tileWidth, tileHeight],
          spatialReference: layer.spatialReference
        })
      }

      /**
       * @description: WMTS tileInfo
       * @param {WMTSLayer} layer
       * @return {TileInfo}
       */
      static parseWMTSTileInfo(layer) {
        if (!layer) {
          Log.error('wmtsLayer未定义')
        }

        // 处理wmts 图层
        // 对于igs服务优先取dpi96的数据信息,没有dpi96_GB，且有028mm_GB信息，则用028mm_GB数据.
        const tileMatrixSets = layer.tileMatrixSets
        const id = layer.activeLayer.tileMatrixSetId
        let tileMatrixSet
        let resolutions
        tileMatrixSet = tileMatrixSets.find(
          (item) => item.id.indexOf('dpi96_GB') > -1
        )
        const isGeographic = layer._spatialReference.isGeographic
        if (tileMatrixSet) {
          resolutions = tileMatrixSet.getTileResolution(
            (0.0254 / 96) * 1000,
            isGeographic
          )
        } else {
          const tileMatrixSet28 = tileMatrixSets.find(
            (item) => item.id.indexOf('028mm_GB') > -1
          )
          if (tileMatrixSet28) {
            tileMatrixSet = tileMatrixSet28
            resolutions = tileMatrixSet.getTileResolution()
          } else {
            tileMatrixSet = tileMatrixSets.find((item) => item.id === id)
            // 如果天地图的3857坐标，比标准3857少一级，第一级增加一层数据
            if (
              layer.url.indexOf('.tianditu.gov.cn/') > -1 &&
              layer.url.indexOf('_w/') > -1
            ) {
              if (tileMatrixSet.tileMatrix.length < 20) {
                const level0 = JSON.parse(
                  JSON.stringify(tileMatrixSet.tileMatrix[0])
                )
                // 第零级ScaleDenominator为 5.916587109e8
                level0.scaleDenominator = Number(level0.scaleDenominator) * 2
                level0.identifier = 0
                level0.matrixHeight = 1
                level0.matrixWidth = 1
                tileMatrixSet.tileMatrix.unshift(level0)
              }
            }
            resolutions = tileMatrixSet.getTileResolution(
              (0.0254 / 96) * 1000,
              isGeographic
            )
          }
        }

        const origin = tileMatrixSet.tileInfo.origin
        return new TileInfo({
          origin,
          lods: tileMatrixSet.tileMatrix.map((tm, index) => {
            return LOD.fromJSON({
              level: index,
              resolution: resolutions[index],
              scale: parseFloat(tm.scaleDenominator)
            })
          }),
          size: [layer.imageWidth, layer.imageHeight],
          spatialReference: SpatialReference.fromJSON(
            layer.spatialReference.toJSON()
          )
        })
      }

      /**
       * @description: 获取lods
       * @param {Number} firstLod 第一级分辨率
       * @param {String} unit 单位，'m' or 'degree'
       * @param {Number} zoom 级数
       * @return {Array<LOD>}
       */
      static getLods(firstLod, unit, zoom) {
        const len = Math.max(0, zoom)
        const lods = []
        const R = 6378137
        const radius = 2 * Math.PI * R
        const pxToM = radius / 360
        for (let i = 0; i < len; i++) {
          const resolution = firstLod / Math.pow(2, i)
          let scale
          if (unit === 'degree') {
            scale = pxToM * resolution
          } else {
            scale = (resolution * 96) / 0.0254
          }
          lods.push(
            new LOD({
              level: i,
              resolution,
              scale
            })
          )
        }
        return lods
      }

      /**
       * 获取grouplayer的坐标系
       * @param {Array<Layer>|Layer} layer
       * @return {Object}
       *
       */
      static getLayerSpatialReference(layer) {
        // 根据添加的图层更改地图视图的坐标系，第一次创建图层时，检查当前的Map中的地图类型，
        // 循环检查当前map中是否有瓦片或WMTS图层，如果有就用该图层的坐标系，
        // 如果没有，就用第一个遇见的矢量或WMS图层的坐标系
        let spatialReference = null
        let referenceLayer = null
        if (
          layer.type === LayerType.igsTile ||
          layer.type === LayerType.arcgisTile ||
          layer.type === LayerType.wmts ||
          layer.type === LayerType.igsVectorTile ||
          layer.type === LayerType.arcgisVectorTile ||
          layer.type === LayerType.igsMapImage ||
          layer.type === LayerType.arcgisMapImage ||
          layer.type === LayerType.wms ||
          layer.type === LayerType.igsFeature ||
          layer.type === LayerType.wfs ||
          layer.type === LayerType.geojson
        ) {
          referenceLayer = layer
          spatialReference = layer.spatialReference
        } else if (layer.type === LayerType.group || Array.isArray(layer)) {
          const layerList = layer.type === LayerType.group ? layer.layers : layer
          if (layerList.length >= 1) {
            // 循环检查当前map中是否有瓦片或WMTS图层，如果有就用该图层的坐标系，
            for (let i = 0; i < layerList.length; i++) {
              const childLayer = layerList[i]
              if (
                childLayer.type === LayerType.igsTile ||
                childLayer.type === LayerType.arcgisTile ||
                childLayer.type === LayerType.wmts ||
                childLayer.type === LayerType.igsVectorTile ||
                childLayer.type === LayerType.arcgisVectorTile
              ) {
                referenceLayer = childLayer
                spatialReference = childLayer.spatialReference
                break
              }
            }
            if (!spatialReference) {
              // 没有瓦片或WMTS图层，循环检查第一个遇见的矢量或WMS图层的坐标系
              for (let i = 0; i < layerList.length; i++) {
                const childLayer = layerList[i]
                if (
                  childLayer.type === LayerType.igsMapImage ||
                  childLayer.type === LayerType.arcgisMapImage ||
                  childLayer.type === LayerType.wms ||
                  childLayer.type === LayerType.igsFeature ||
                  childLayer.type === LayerType.wfs ||
                  childLayer.type === LayerType.geojson
                ) {
                  referenceLayer = childLayer
                  spatialReference = childLayer.spatialReference
                  break
                }
              }
            }
          }
        }
        if (referenceLayer) {
          referenceLayer._isSRLayer = true
          if (referenceLayer.loaded) {
            referenceLayer._isSRLayer = true
          } else {
            // 如果当前参考系图层没有加载完成，则不当做视图参考系
            referenceLayer = null
            spatialReference = null
          }
        }
        return { spatialReference, referenceLayer }
      }

      /**
       * 获取grouplayer的空间参考系
       * @param {Collection<Layer>} layers
       * @return {Object}
       *
       */
      static getSpatialReference(layers) {
        const layerList = []
        layers.forEach((layer) => {
          if (layer.type === LayerType.group) {
            const groupReference = this.getLayerSpatialReference(layer)
            layerList.push(groupReference.referenceLayer)
          } else {
            layerList.push(layer)
          }
        })
        const reference = this.getLayerSpatialReference(layerList)
        return reference
      }

      /**
       * 设置MapImageLayer、FeatureLayer的空间参考系
       * @param {Collection<Layer>} layers 需要设置参考系的图层集合
       * @param {SpatialReference} spatialReference 被设置的spatialReference
       * @param {SpatialReference} isBasemapLayer 当前参考图层是否为基础底图
       *
       */
      static setLayerSpatialReference(layers, spatialReference, isBasemapLayer) {
        if (spatialReference) {
          layers.forEach((layer) => {
            if (
              layer.type === LayerType.igsMapImage ||
              layer.type === LayerType.arcgisMapImage ||
              layer.type === LayerType.feature
            ) {
              // 如果当前参考图层不是基础底图，则基础底图图层不受该参考系影响
              if (!isBasemapLayer && layer._isBasemapLayer) {
                return
              }
              if (
                layer.loaded &&
                (!layer.spatialReference ||
                  (layer.spatialReference &&
                    layer.spatialReference.wkid !== spatialReference.wkid))
              ) {
                layer.spatialReference = spatialReference
                layer._extentSrc = Projection.project(
                  layer._extentSrc,
                  spatialReference
                )
              }
            }
          })
        }
      }
    }