    import {
      Log,
      Projection,
      SpatialReference,
      Point,
      GeometryType,
      Color
    } from '@mapgis/webclient-common'
    import * as L from '@mapgis/leaflet'

    class LeafletPlugin {
      /**
       * @description 颜色转换
       * @private
       * @param {Color|String} color
       * @return {String}
       */
      static convertColorToRgb(color) {
        if (color instanceof Color) {
          return color.toCssRGBAString()
        }
        return color
      }

      /**
       * @description: 转换为经纬度坐标系下几何
       * @param {*} geometry
       * @return {*}
       */
      static convertLngLatGeometry(geometry) {
        if (!geometry || !geometry.spatialReference) return geometry
        if (String(geometry.spatialReference.wkid) !== '4326') {
          return Projection.project(geometry, new SpatialReference('EPSG:4326'))
        }
        return geometry
      }

      /**
       * @description: 转换裁剪区域
       * @param {Polygon|Extent|Circle|null} clippingArea
       * @return {Number[][][]|null}
       */
      static convertClippingArea(clippingArea) {
        if (!clippingArea) return clippingArea
        let clippingAreaCoords = null
        switch (clippingArea.type) {
          case GeometryType.polygon:
            clippingAreaCoords =
              LeafletPlugin.convertLngLatGeometry(clippingArea).coordinates
            break
          case GeometryType.circle: {
            const circle = LeafletPlugin.convertLngLatGeometry(clippingArea)
            clippingAreaCoords = circle.toPolygon().coordinates
            break
          }
          case GeometryType.extent: {
            const extent = LeafletPlugin.convertLngLatGeometry(clippingArea)
            const { xmin, xmax, ymin, ymax } = extent
            clippingAreaCoords = [
              [
                [xmin, ymax],
                [xmax, ymax],
                [xmax, ymin],
                [xmin, ymin],
                [xmin, ymax]
              ]
            ]
            break
          }
          default:
            break
        }

        return clippingAreaCoords
      }

      /**
       * @description 转换线样式
       * @private
       * @param {String} lineStyle
       * @param {String} isButt
       * @return {String}
       */
      static convertLineDash(lineStyle, isButt) {
        switch (lineStyle) {
          case 'dash':
            return isButt ? [4, 3] : [3, 4]
          case 'dash-dot':
            return isButt ? [4, 3, 1, 3] : [3, 4, 0, 4]
          case 'dot':
            return isButt ? [1, 3] : [0, 4]
          case 'long-dash':
            return isButt ? [8, 3] : [7, 4]
          case 'long-dash-dot':
            return isButt ? [8, 3, 1, 3] : [7, 4, 0, 4]
          case 'long-dash-dot-dot':
            return isButt ? [8, 3, 1, 3, 1, 3] : [7, 4, 0, 4, 0, 4]
          case 'short-dash':
            return isButt ? [4, 1] : [3, 2]
          case 'short-dash-dot':
            return isButt ? [4, 1, 1, 1] : [3, 2, 0, 2]
          case 'short-dash-dot-dot':
            return isButt ? [4, 1, 1, 1, 1, 1] : [3, 2, 0, 2, 0, 2]
          case 'short-dot':
            return isButt ? [1, 1] : [0, 2]
          case 'solid':
          case 'none':
            return undefined
          default:
            return undefined
        }
      }

      static calcLineMarkerDetail(coords) {
        if (!coords || (Array.isArray(coords) && coords.length <= 1)) {
          Log.error('计算线样式首尾marker错误,传入几何数组不合法')
        }
        // 此处计算角度可能在不同坐标系下会发生偏移
        const p1 = coords[0]
        const p2 = coords[1]
        const p3 = coords[coords.length - 2]
        const p4 = coords[coords.length - 1]

        const angle1 =
          360 -
          ((((Math.atan2(p2[1] - p1[1], p2[0] - p1[0]) * 180) / Math.PI + 180) %
            360) -
            90)
        const angle2 =
          360 -
          ((((Math.atan2(p3[1] - p4[1], p3[0] - p4[0]) * 180) / Math.PI + 180) %
            360) -
            90)

        const _latlng1 = Projection.project(
          new Point({
            coordinates: p1
          }),
          new SpatialReference('EPSG:4326')
        ).coordinates
        const _latlng2 = Projection.project(
          new Point({
            coordinates: p4
          }),
          new SpatialReference('EPSG:4326')
        ).coordinates

        const latlng1 = L.latLng(_latlng1[1], _latlng1[0])
        const latlng2 = L.latLng(_latlng2[1], _latlng2[0])

        return {
          latlng1,
          latlng2,
          angle1,
          angle2
        }
      }

      /**
       * 使用canvas画布。测量文本以计算并返回给定字体的给定文本的宽度(以像素为单位)。
       * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
       * 要呈现的文本
       * @private
       * @param {String} text The text to be rendered.
       * 用于呈现文本的css字体描述符
       * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
       * @param {Object} styleObject 样式对象
       */
      static getTextWidth(text, font) {
        // 重用canvas对象以获得更好的性能
        // re-use canvas object for better performance
        const canvas =
          LeafletPlugin.getTextWidth.canvas ||
          (LeafletPlugin.getTextWidth.canvas = document.createElement('canvas'))
        const context = canvas.getContext('2d')
        context.font = font
        const metrics = context.measureText(text)
        return metrics.width
      }

      /**
       * @description: 获取几何区域中心
       * @param {*} geometry
       * @return {*}
       */
      static getAreaCenter(geometry) {
        let p
        switch (geometry.type) {
          case GeometryType.point: {
            p = geometry.clone()
            break
          }
          case GeometryType.multiPoint:
          case GeometryType.lineString:
          case GeometryType.multiLineString:
          case GeometryType.multiPolygon: {
            p = geometry.extent.center
            break
          }
          case GeometryType.polygon: {
            p = geometry.centroid
            break
          }
          case GeometryType.extent: {
            p = geometry.center
            break
          }
          case GeometryType.circle: {
            p = geometry.center
            break
          }
          default: {
            p = geometry.extent.center
          }
        }
        const _latlng = LeafletPlugin.convertLngLatGeometry(p).coordinates
        const latlng = L.latLng(_latlng[1], _latlng[0])
        return latlng
      }

      /**
       * @description: 设置innerLayer透明度
       * @param {*} innerLayer
       * @param {*} opacity
       * @param {*} visible
       * @return {*}
       */
      static setVisibleOpacity(innerLayer, opacity, visible) {
        if (!innerLayer) return
        // 设置图层透明度
        innerLayer.layerOpacity = opacity
        // 设置图层显示或隐藏
        innerLayer.layerVisible = visible
        LeafletPlugin.setGraphicVisibleOpacity(innerLayer, opacity, visible)
      }

      /**
       * @description: 设置几何图元透明度
       * @param {*} graphic
       * @param {*} opacity
       * @param {*} visible
       * @return {*}
       */
      static setGraphicVisibleOpacity(graphic, opacity, visible) {
        if (graphic.setStyle) {
          graphic.setStyle({
            opacity: visible ? opacity : 0,
            fillOpacity: visible ? opacity : 0
          })
        }
        if (graphic instanceof L.Marker) {
          graphic.setOpacity(visible ? opacity : 0)
        }
        if (graphic.eachLayer) {
          graphic.eachLayer(function (subGraphic) {
            LeafletPlugin.setGraphicVisibleOpacity(subGraphic, opacity, visible)
          })
        }
        // 解决聚类专题图聚合点无法设置透明度问题
        if (graphic._nonPointGroup) {
          LeafletPlugin.setGraphicVisibleOpacity(
            graphic._nonPointGroup,
            opacity,
            visible
          )
        }
        if (graphic._featureGroup) {
          LeafletPlugin.setGraphicVisibleOpacity(
            graphic._featureGroup,
            opacity,
            visible
          )
        }
      }
    }

    export default LeafletPlugin