    import * as L from '@mapgis/leaflet'
    // 来源 link https://github.com/huiyan-fe/mapv/blob/master/src/map/leaflet-map/MapVRenderer.js
    const mapv = window.mapv || {}
    const Layer = mapv.baiduMapLayer ? mapv.baiduMapLayer.__proto__ : Function

    /**
     * @class L.zondy.MapvBaseLayer
     * @classdesc MapV的核心渲染图层，这里是直接集成的baiduMapLayer，原因在于mapv的对外导出exports的就是baiduMapLayer
     * @param map - {Object} 传入的leaflet的地图对象
     * @param dataSet - {MapvDataSet} 传入的mapv的属性。 <br>
     * @param options - {MapvOption} 可选参数。<br>
     * @param leafletLayer - {Object} 传入的leaflet的实际渲染图层。<br>
     *
     * @example
     options = {
        zIndex: 1, // 层级
        size: 5, // 大小值
        unit: 'px', // 'px': 以像素为单位绘制,默认值。'm': 以米制为单位绘制，会跟随地图比例放大缩小
        mixBlendMode: 'normal', // 不同图层之间的叠加模式，参考[https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode)
        fillStyle: 'rgba(200, 200, 50, 1)', // 填充颜色
        strokeStyle: 'rgba(0, 0, 255, 1)', // 描边颜色
        lineWidth: 4, // 描边宽度
        globalAlpha: 1, // 透明度
        globalCompositeOperation: 'lighter', // 颜色叠加方式
        coordType: 'bd09ll', // 可选百度墨卡托坐标类型bd09mc和百度经纬度坐标类型bd09ll(默认)
        shadowColor: 'rgba(255, 255, 255, 1)', // 投影颜色
        shadowBlur: 35,  // 投影模糊级数
        updateCallback: function (time) { // 重绘回调函数，如果是时间动画、返回当前帧的时间
        },
        shadowOffsetX: 0,
        shadowOffsetY: 0,
        context: '2d', // 可选2d和webgl，webgl目前只支持画simple模式的点和线
        lineCap: 'butt',
        lineJoin: 'miter',
        miterLimit: 10,
        methods: { // 一些事件回调函数
            click: function (item) { // 点击事件，返回对应点击元素的对象值
                console.log(item);
            },
            mousemove: function(item) { // 鼠标移动事件，对应鼠标经过的元素对象值
                console.log(item);
            }
        },
        animation: {
            type: 'time', // 按时间展示动画
            stepsRange: { // 动画时间范围,time字段中值
                start: 0,
                end: 100
            },
            trails: 10, // 时间动画的拖尾大小
            duration: 5, // 单个动画的时间，单位秒
        }
    }
     */
    export class MapvBaseLayer extends Layer {
      constructor(map, dataSet, options, leafletLayer) {
        super(map, dataSet, options)

        if (!Layer) {
          return
        }

        this.map = map // 此处的map是外面传入的leaflet的map对象
        this.dataSet = dataSet
        this.options = options

        options = options || {}

        this.init(options)
        this.argCheck(options)

        this.initDevicePixelRatio()

        this.canvasLayer = leafletLayer

        this.clickEvent = this.clickEvent.bind(this)
        this.mousemoveEvent = this.mousemoveEvent.bind(this)

        this.bindEvent()
      }

      /**
       * @function L.zondy.MapvBaseLayer.prototype.clickEvent
       * @description 百度mapv原本的事件只有clickEvent和mousemoveEvent
       * @param e - {Object}  点击事件对象 {latlng, layerPoint, containerPoint, originalEvent}
       * @example
       * //mapv.map.Layer.clickEvent
       * clickEvent(pixel, e) {
       *    var dataItem = this.isPointInPath(this.getContext(), pixel);
       *    if (dataItem) {
       *       this.options.methods.click(dataItem, e);
       *    } else {
       *       this.options.methods.click(null, e);
       *    }
       *  }
       */
      clickEvent(e) {
        const offset = this.map.containerPointToLayerPoint([0, 0]) // this.map.getPixelOrigin()
        const devicePixelRatio = this.devicePixelRatio || 1
        const canvasPoint = e.layerPoint
        const pixel = {
          x: (canvasPoint.x - offset.x) / devicePixelRatio,
          y: (canvasPoint.y - offset.y) / devicePixelRatio
        }
        // super.clickEvent(pixel, e);
      }

      /**
       * @function L.zondy.MapvBaseLayer.prototype.mousemoveEvent
       * @description 百度mapv原本的事件只有clickEvent和mousemoveEvent
       * @param e - {Object}  点击事件对象 {latlng, layerPoint, containerPoint, originalEvent}
       * @example
       * //mapv.map.Layer.mousemoveEvent
       * mousemoveEvent(pixel, e) {
       *   var dataItem = this.isPointInPath(this.getContext(), pixel);
       *   if (dataItem) {
       *       this.options.methods.mousemove(dataItem, e);
       *   } else {
       *       this.options.methods.mousemove(null, e);
       *   }
       * }
       */
      mousemoveEvent(e) {
        if (!e) {
          return
        }
        const offset = this.map.containerPointToLayerPoint([0, 0]) // this.map.getPixelOrigin()
        const devicePixelRatio = this.devicePixelRatio || 1
        const canvasPoint = e.layerPoint
        const pixel = {
          x: (canvasPoint.x - offset.x) / devicePixelRatio,
          y: (canvasPoint.y - offset.y) / devicePixelRatio
        }
        // super.mousemoveEvent(pixel, e);
      }

      addAnimatorEvent() {
        /* this.map.on('movestart', this.animatorMovestartEvent.bind(this));
        this.map.on('moveend', this.animatorMoveendEvent.bind(this)); */
      }

      animatorMovestartEvent() {
        const animationOptions = this.options.animation
        if (this.isEnabledTime() && this.animator) {
          this.steps.step = animationOptions.stepsRange.start
          // this.animator.stop();
        }
      }

      animatorMoveendEvent() {
        if (this.isEnabledTime() && this.animator) {
          // this.animator.start();
        }
      }

      bindEvent() {
        const map = this.map

        if (this.options.methods) {
          if (this.options.methods.click) {
            map.on('click', this.clickEvent)
          }
          if (this.options.methods.mousemove) {
            map.on('mousemove', this.mousemoveEvent)
          }
        }
      }

      unbindEvent() {
        const map = this.map

        if (this.options.methods) {
          if (this.options.methods.click) {
            map.removeListener('click', this.clickEvent)
          }
          if (this.options.methods.mousemove) {
            map.removeListener('mousemove', this.mousemoveEvent)
          }
        }
      }

      /**
       * @function L.zondy.MapvBaseLayer.prototype.initDevicePixelRatio
       * @description window.devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例。
       * 公式表示就是：window.devicePixelRatio = 物理像素 / dips,该函数主要应用与移动设备
       */
      initDevicePixelRatio() {
        this.devicePixelRatio = window.devicePixelRatio || 1
      }

      getContext() {
        return this.canvasLayer.getCanvas().getContext(this.context)
      }

      _canvasUpdate(time) {
        // 重绘mapv canvas图层
        if (!this.canvasLayer || this.canvasLayer.disposeFlag) {
          return
        }

        const self = this
        const map = this.map

        const animationOptions = self.options.animation

        const context = this.getContext()

        if (self.isEnabledTime()) {
          if (time === undefined) {
            this.clear(context)
            return
          }
          if (this.context === '2d') {
            context.save()
            context.globalCompositeOperation = 'destination-out'
            context.fillStyle = 'rgba(0, 0, 0, .1)'
            context.fillRect(0, 0, context.canvas.width, context.canvas.height)
            context.restore()
          }
        } else {
          this.clear(context)
        }

        if (this.context === '2d') {
          for (const key in self.options) {
            context[key] = self.options[key]
          }
        } else {
          context.clear(context.COLOR_BUFFER_BIT)
        }

        if (
          (self.options.minZoom && map.getZoom() < self.options.minZoom) ||
          (self.options.maxZoom && map.getZoom() > self.options.maxZoom)
        ) {
          return
        }

        const topLeft = map.getBounds().getNorthWest()

        const offset = map.latLngToLayerPoint(topLeft)
        const dataGetOptions = {
          // fromColumn: self.options.coordType == 'bd09mc' ? 'coordinates' : 'coordinates_mercator',
          transferCoordinate(coordinate) {
            // get center from the map (projected)
            const point = map.latLngToLayerPoint(
              new L.LatLng(coordinate[1], coordinate[0])
            )
            if (self.options.draw === 'heatmap') {
              point.x /= self.devicePixelRatio
              point.y /= self.devicePixelRatio
            }
            return [point.x - offset.x, point.y - offset.y]
          }
        }

        if (time !== undefined) {
          dataGetOptions.filter = function (item) {
            const trails = animationOptions.trails || 10
            return time && item.time > time - trails && item.time < time
          }
        }

        const data = self.dataSet.get(dataGetOptions)

        this.processData(data)

        if (self.options.unit === 'm' && self.options.size) {
          // self.options._size = self.options.size / zoomUnit;
          self.options._size = self.options.size
        } else {
          self.options._size = self.options.size
        }

        const originpoint = map.latLngToLayerPoint(L.latLng(0, 0))
        const pixel = {
          x: originpoint.x - offset.x,
          y: originpoint.y - offset.y
        }

        this.drawContext(context, new mapv.DataSet(data), self.options, pixel)
        if (
          self.options.updateCallback &&
          self.options.updateCallback instanceof Function
        ) {
          self.options.updateCallback(time)
        }
      }

      init(options) {
        const self = this

        self.options = options

        this.initDataRange(options)

        this.context = self.options.context || '2d'

        if (self.options.zIndex && self.canvasLayer) {
          self.canvasLayer.setZIndex(self.options.zIndex)
        }

        this.initAnimator()
      }

      updateData(data, options) {
        let _data = data
        if (_data && _data.get) {
          _data = _data.get()
        }
        if (_data !== undefined) {
          this.dataSet.set(_data)
        }

        super.update({
          options
        })
      }

      addData(data, options) {
        let _data = data
        if (data && data.get) {
          _data = data.get()
        }
        this.dataSet.add(_data)
        this.update({
          options
        })
      }

      draw() {
        this.canvasLayer.draw()
      }

      // 该函数从mapv/canvas/clear中提取
      clear(context) {
        if (context && context.clearRect) {
          context.clearRect(0, 0, context.canvas.width, context.canvas.height)
        }
        // context.canvas.width = context.canvas.width;
        // context.canvas.height = context.canvas.height;
      }
    }