    import { Zondy, FeatureSet, Extent } from '@mapgis/webclient-common'
    import * as L from '@mapgis/leaflet'
    // eslint-disable-next-line import/no-extraneous-dependencies
    import { ShapeFactory, ThemeVector } from '@mapgis/webclient-graphic-render'
    import ThemeLayer from './ThemeLayer'

    /**
     * @class Zondy.ThemeLayer.GeoFeatureThemeLayer
     * @classdesc  地理几何专题要素型专题图层基类。此类型专题图的专题要素形状就是由 feature.geometry 决定。此类不建议直接实例化调用。
     * @extends Zondy.ThemeLayer.ThemeLayer
     * @param {string} name - 专题图名。
     * @param {Object} options - 需要设置的参数对象。
     * @param {string} [options.id] - 专题图层 ID。默认使用 CommonUtil.createUniqueID("themeLayer_") 创建专题图层 ID。
     * @param {number} [options.opacity=1] - 图层透明度。
     * @param {number} [options.nodesClipPixel=2] - 节点抽稀像素距离。
     * @param {boolean} [options.isHoverAble=false] -  图形是否在 hover 时高亮。
     * @param {boolean} [options.isMultiHover=false] - 是否多图形同时高亮，用于高亮同一个数据对应的所有图形（如：多面）。
     * @param {boolean} [options.isClickAble=true] - 图形是否可点击。
     * @param {boolean} [options.isAllowFeatureStyle=false] -  是否允许 feature 样式（style） 中的有效属性应用到专题图层。禁止对专题要素使用数据（feature）的 style。此属性可强制将数据 feature 的 style 中有效属性应用到专题要素上，且拥有比图层 style 和 styleGroups 更高的优先级，使专题要素的样式脱离专题图层的控制。可以通过此方式实现对特殊数据（feature） 对应专题要素赋予独立 style。
     * @fires Zondy.ThemeLayer.GeoFeatureThemeLayer#beforefeaturesadded
     */
    const GeoFeatureThemeLayer = ThemeLayer.extend({
      options: {
        // {Number} 节点抽稀像素距离，默认值 2。
        nodesClipPixel: 2,

        // {Boolean} 图形是否在 hover 时高亮 ，默认值：false。
        isHoverAble: false,

        // {Boolean} 是否多图形同时高亮，用于高亮同一个数据对应的所有图形（如：多面），默认值：false。
        isMultiHover: false,

        // {Boolean} 图形是否可点击，默认 true
        isClickAble: true,
        // 是否允许 feature 样式（style） 中的有效属性应用到专题图层。
        // 默认值为： false，禁止对专题要素使用数据（feature）的 style。
        // 此属性可强制将数据 feature 的 style 中有效属性应用到专题要素上，且拥有比图层 style 和 styleGroups 更高的优先级，使专题要素的样式脱离专题图层的控制。可以通过此方式实现对特殊数据（feature） 对应专题要素赋予独立 style。
        isAllowFeatureStyle: false
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.initialize
       * @description 初始化。
       * @param {string} name - 专题图名。
       * @param {Object} options - 需要设置的参数对象。
       */
      initialize(name, options) {
        ThemeLayer.prototype.initialize.call(this, name, options)
        L.Util.setOptions(this, options)
        const me = this
        me.cache = {}
        me.cacheFields = []
        me.style = {}
        me.highlightStyle = {}
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.addFeatures
       * @description 向专题图图层中添加数据。
       * @param {Object} features - 待填加的要素。
       */
      addFeatures(features) {
        const me = this

        /**
         * @event Zondy.ThemeLayer.GeoFeatureThemeLayer#beforefeaturesadded
         * @description 向专题图图层中添加数据之前触发。
         * @property {Object} features - 事件对象。
         */
        me.fire('beforefeaturesadded', { features })
        if (features instanceof FeatureSet) {
          const attrs = null
          const attstruct = features.AttStruct
          const feaArr = features.SFEleArray
          if (feaArr !== null && feaArr.length > 0) {
            for (let j = 0; j < feaArr.length; j++) {
              const feature = feaArr[j]
              if (feature.AttValue !== null && feature.AttValue.length > 0) {
                const attrs = {}
                for (let i = 0; i < feature.AttValue.length; i++) {
                  attrs[attstruct.FldName[i]] = feature.AttValue[i]
                }
                attrs['FID'] = feature.FID
              }
              feature.attributes = attrs
              me.features.push(feature)
            }
          }
        }
        if (!me.isCustomSetMaxCacheCount) {
          me.maxCacheCount = me.features.length * 5
        }

        if (!me.renderer) {
          return
        }
        // 绘制专题要素
        if (me._map) {
          me.redrawThematicFeatures(me._map.getBounds())
        } else {
          me.redrawThematicFeatures()
        }
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.removeFeatures
       * @description 从专题图中删除 feature。这个函数删除所有传递进来的矢量要素。参数中的 features 数组中的每一项，必须是已经添加到当前图层中的 feature。
       * @param {Object} features - 要删除的要素。
       */
      removeFeatures(features) {
        // eslint-disable-line no-unused-vars
        this.clearCache()
        ThemeLayer.prototype.removeFeatures.call(this, arguments)
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.removeAllFeatures
       * @description 清除当前图层所有的矢量要素。
       */
      removeAllFeatures() {
        this.clearCache()
        ThemeLayer.prototype.removeAllFeatures.call(this, arguments)
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.redrawThematicFeatures
       * @description 重绘所有专题要素。
       *              此方法包含绘制专题要素的所有步骤，包含用户数据到专题要素的转换，抽稀，缓存等步骤。
       *              地图漫游时调用此方法进行图层刷新。
       * @param {L.bounds} bounds - 重绘的范围。
       */
      redrawThematicFeatures(bounds) {
        const me = this
        // 获取高亮专题要素对应的用户 id
        const hoverone = me.renderer.getHoverOne()
        let hoverFid = null
        if (hoverone && hoverone.refDataID) {
          hoverFid = hoverone.refDataID
        }
        if (bounds && bounds instanceof L.LatLngBounds) {
          const crs = this._map.options.crs
          bounds = L.bounds(
            crs.project(bounds.getSouthWest()),
            crs.project(bounds.getNorthEast())
          )
          bounds = new Extent(
            bounds.min.x,
            bounds.min.y,
            bounds.max.x,
            bounds.max.y
          )
        }
        // 清除当前所有可视元素
        me.renderer.clearAll()

        const features = me.features
        const cache = me.cache
        const cacheFields = me.cacheFields
        const cmZoom = me._map.getZoom()

        const maxCC = me.maxCacheCount

        for (let i = 0, len = features.length; i < len; i++) {
          const feature = features[i]
          const feaBounds = feature.bound

          // 剔除当前视图（地理）范围以外的数据
          if (bounds && !bounds.intersectsBounds(feaBounds)) {
            continue
          }

          // 缓存字段
          const fields = `${feature.FID}_zoom_${cmZoom.toString()}`
          if (cache[fields]) {
            cache[fields].updateAndAddShapes()
            continue
          }

          const thematicFeature = me.createThematicFeature(features[i])
          // 检查 thematicFeature 是否有可视化图形
          if (thematicFeature.getShapesCount() < 1) {
            continue
          }
          // 加入缓存
          cache[fields] = thematicFeature
          cacheFields.push(fields)
          // 缓存数量限制
          if (cacheFields.length > maxCC) {
            const fieldsTemp = cacheFields[0]
            cacheFields.splice(0, 1)
            delete cache[fieldsTemp]
          }
        }

        me.renderer.render()

        // 地图漫游后，重新高亮图形
        if (hoverFid && me.options.isHoverAble && me.options.isMultiHover) {
          const hShapes = this.getShapesByFeatureID(hoverFid)
          this.renderer.updateHoverShapes(hShapes)
        }
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.createThematicFeature
       * @description 创建专题要素。
       * @param {Object} feature - 要创建的要素。
       */
      createThematicFeature(feature) {
        const me = this
        const style = me.getStyleByData(feature)
        // 创建专题要素时的可选参数
        const options = {}
        options.nodesClipPixel = me.options.nodesClipPixel
        options.isHoverAble = me.options.isHoverAble
        options.isMultiHover = me.options.isMultiHover
        options.isClickAble = me.options.isClickAble
        options.highlightStyle = ShapeFactory.transformStyle(me.highlightStyle)

        // 将数据转为专题要素（Vector）
        const thematicFeature = new ThemeVector(
          feature,
          me,
          ShapeFactory.transformStyle(style),
          options
        )

        // 直接添加图形到渲染器
        for (let m = 0; m < thematicFeature.shapes.length; m++) {
          me.renderer.addShape(thematicFeature.shapes[m])
        }

        return thematicFeature
      },
      getStyleByData(feat) {
        // 子类必须实现此方法
      },
      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.redraw
       * @description 重绘该图层。
       */
      redraw() {
        this.clearCache()
        return ThemeLayer.prototype.redraw.apply(this, arguments)
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.clearCache
       * @description 清除缓存数据。
       */
      clearCache() {
        this.cache = {}
        this.cacheFields = []
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.clear
       * @description 清除的内容包括数据（features） 、专题要素、缓存。
       */
      clear() {
        const me = this
        me.renderer.clearAll()
        me.renderer.refresh()
        me.removeAllFeatures()
        me.clearCache()
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.getCacheCount
       * @description 获取当前缓存数量。
       * @returns {number} 返回当前缓存数量。
       */
      getCacheCount() {
        return this.cacheFields.length
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.setMaxCacheCount
       * @description 设置最大缓存数量。
       * @param {number} cacheCount - 最大缓存量。
       */
      setMaxCacheCount(cacheCount) {
        if (isNaN(cacheCount)) {
          return
        }
        this.maxCacheCount = cacheCount
        this.isCustomSetMaxCacheCount = true
      },

      /**
       * @function Zondy.ThemeLayer.GeoFeatureThemeLayer.prototype.getShapesByFeatureID
       * @description 通过 FeatureID 获取 feature 关联的所有图形。如果不传入此参数，函数将返回所有图形。
       * @param {number} featureID - 要素 ID。
       */
      getShapesByFeatureID(featureID) {
        const me = this
        const list = []
        const shapeList = me.renderer.getAllShapes()

        if (!featureID) {
          return shapeList
        }

        for (let i = 0, len = shapeList.length; i < len; i++) {
          const si = shapeList[i]
          if (si.refDataID && featureID === si.refDataID) {
            list.push(si)
          }
        }
        return list
      }
    })

    Zondy.ThemeLayer.GeoFeatureThemeLayer = GeoFeatureThemeLayer
    export default GeoFeatureThemeLayer