import { FetchServer } from '@mapgis/webclient-common'
import {
  getFonts,
  getLayers,
  getSpritePng,
  getVectorTileSource
} from './MapgisVectorTileLayer'
import VectorTileStyle from './MapgisVectorTileStyle'
import VectorTileProvider from './VectorTileProvider'

class VectorTileLayer {
  constructor(viewer, options) {
    this.viewer = viewer
    this.scene = this.viewer.scene

    this.url = options.styleUrl
    if (!this.url && options.ip) {
      this.url = `http://${options.ip}:${options.port}/igs/rest/mrcs/vtiles/0/${options.layerName}`
    }

    this.options = options
    this.callback = options.callback
    this.token = options.token || ''
    this.opacity = options.opacity || 1
    this.vectortilejson = options.vectortilejson
    this.threadId = options.threadId || Math.random() * 10000
    this.show = options.show || true
    this.style = options.style
    this.tilingScheme = options.tilingScheme
    this.provider = null
    this.maximumLevel = options.maximumLevel || 20
    this.minimumLevel = options.minimumLevel || 0
    this.labelsRenderMode = options.labelsRenderMode || 'off-screen'
    this._dynamicEntityVisualizer =
      this.labelsRenderMode === 'on-screen'
        ? new Cesium.DynamicEntityVisualizer(viewer.scene, {})
        : null
    this.initDevicePixelRatio()
    this._fetchService = new FetchServer('', {})
    this._addCallback = options.addCallback || undefined
    this._wgs84Extent = options.wgs84Extent
    this._labelsNoteStyle = options.labelsNoteStyle

    if (this.style) {
      if (typeof this.style === 'string') {
        this.url = this.style
        this.requestVectortileJson()
      } else {
        this.vectortilejson = this.style
        this.requestStyleData(this.vectortilejson)
      }
    }
  }

  initDevicePixelRatio() {
    this.devicePixelRatio = window.devicePixelRatio || 1
  }

  bindEvent() {
    // 下面几个是cesium专属事件,clickEvent和mousemoveEvent是mapv内部自带的方法不放出来
    this.innerMoveStart = this.moveStartEvent.bind(this)
    this.innerMoveEnd = this.moveEndEvent.bind(this)

    this.innnerZoomStart = this.zoomStartEvent.bind(this)
    this.innnerZoomEnd = this.zoomEndEvent.bind(this)
  }

  /**
   * 通过url获取矢量瓦片json对象
   */
  requestVectortileJson() {
    if (!this.vectortilejson) {
      // 发起请求
      const that = this
      this._fetchService.request({
        url: this.url,
        method: 'GET',
        success(result) {
          that.vectortilejson = result
          that.requestStyleData(that.vectortilejson)
        }
      })
    }
  }

  /**
   * 通过矢量瓦片json对象，获取样式参数
   * @function module:客户端渲染.VectorTileLayer.prototype.requestStyleData
   * @param {Object} vectortilejson 矢量瓦片对象 Mapbox-Style-Spec样式对象
   * @see https://docs.mapbox.com/mapbox-gl-js/style-spec/
   */
  requestStyleData(vectortilejson) {
    this.vectortilejson = vectortilejson
    const layers = getLayers(vectortilejson)
    const sources = getVectorTileSource(vectortilejson)
    const spritepng = getSpritePng(vectortilejson)
    // 发起请求
    const that = this
    this._fetchService.request({
      url: `${vectortilejson.sprite}.json`,
      method: 'GET',
      success(result) {
        that.styleData = {
          vectortilejson,
          layers,
          spritedata: result,
          spritepng,
          fonts: getFonts,
          sources
        }
        that.addLayer(that.styleData)
        if (that._addCallback && that._addCallback instanceof Function) {
          that._addCallback()
        }
      }
    })
  }

  getLayer() {
    return self.provider ? self.provider : undefined
  }

  /**
   * 首先构造矢量瓦片样式，再添加图层
   * @function module:客户端渲染.VectorTileLayer.prototype.addLayer
   * @param {Object} styleData 矢量瓦片样式参数 Mapbox-Style-Spec样式对象
   * @see https://docs.mapbox.com/mapbox-gl-js/style-spec/
   */
  addLayer(styleData) {
    const vectortileStyle = VectorTileStyle(
      styleData.vectortilejson,
      Object.keys(styleData.vectortilejson.sources),
      null,
      styleData.spritedata,
      styleData.spritepng,
      styleData.fonts
    )

    if (styleData.sources.length > 0) {
      const source = styleData.sources[0]
      const vectortile = VectorTileProvider(Cesium, {
        key: this.token,
        url: source.tiles[0],
        style: vectortileStyle,
        opacity: this.opacity,
        threadId: this.threadId,
        show: this.show,
        tilingScheme: this.tilingScheme,
        maximumLevel: this.maximumLevel,
        minimumLevel: this.minimumLevel,
        scene:this.scene,
        dynamicEntityVisualizer: this._dynamicEntityVisualizer,
        labelsRenderMode: this.labelsRenderMode,
        wgs84Extent: this._wgs84Extent,
        labelsNoteStyle: this._labelsNoteStyle
      })
      this.provider = this.viewer.imageryLayers.addImageryProvider(vectortile)
      this.provider.show = this.show

      if (this.callback) {
        this.callback({ imageryLayer: this.provider })
      }
    }
  }

  /**
   * @description 设置布局属性
   * @function module:客户端渲染.VectorTileLayer.prototype.updateStyle
   * @param {Object} mvtStyle
   */
  updateStyle(mvtStyle) {
    if (!this.styleData) return
    this.styleData.vectortilejson = mvtStyle
    this.remove()
    this.addLayer(this.styleData)
  }

  /**
   * @description 设置布局属性
   * @function module:客户端渲染.VectorTileLayer.prototype.setLayoutProperty
   * @param {String} layer
   * @param {String} key
   * @param {Object} value
   */
  setLayoutProperty(layerId, key, value) {
    if (!this.vectortilejson || !this.vectortilejson.layers) return
    const { layers } = this.vectortilejson
    const finds = layers.filter((l) => {
      return l.id === layerId
    })
    const layer = finds && finds.length > 0 ? finds[0] : undefined
    if (!layer) return
    layer.layout = layer.layout || {}
    layer.layout[key] = value
    this.styleData.vectortilejson = this.vectortilejson
    this.remove()
    this.addLayer(this.styleData)
  }

  /**
   * @description 设置画笔属性
   * @function module:客户端渲染.VectorTileLayer.prototype.setPaintProperty
   * @param {String} layerId
   * @param {String} key
   * @param {Object} value
   */
  setPaintProperty(layerId, key, value) {
    if (!this.vectortilejson || !this.vectortilejson.layers) return
    const { layers } = this.vectortilejson
    const finds = layers.filter((l) => {
      return l.id === layerId
    })
    const layer = finds && finds.length > 0 ? finds[0] : undefined
    if (!layer) return
    layer.paint = layer.paint || {}
    layer.paint[key] = value
    this.remove()
    this.addLayer(this.styleData)
  }

  /**
   * @description 设置过滤属性
   * @function module:客户端渲染.VectorTileLayer.prototype.setFilter
   * @param {String} layerId
   * @param {Array} rule
   */
  setFilter(layerId, rule) {
    if (!this.vectortilejson || !this.vectortilejson.layers) return
    const { layers } = this.vectortilejson
    const finds = layers.filter((l) => {
      return l.id === layerId
    })
    const layer = finds && finds.length > 0 ? finds[0] : undefined
    if (!layer) return
    layer.filter = layer.filter || {}
    layer.filter = rule
    this.remove()
    this.addLayer(this.styleData)
  }

  unbindEvent() {}

  moveStartEvent() {}

  moveEndEvent() {}

  zoomStartEvent() {}

  zoomEndEvent() {}

  /**
   * 销毁图层-实际调用remove，为了接口保持一致
   * @function module:客户端渲染.VectorTileLayer.prototype.destroy
   */
  destroy() {
    this.remove()
  }

  /**
   * 设置图层的可见性
   * @param visible
   */
  setVisible(visible) {
    if (this.provider) {
      this.provider.show = visible
    }
  }

  /**
   * 移除图层
   * @function module:客户端渲染.VectorTileLayer.prototype.remove
   */
  remove() {
    const self = this
    if (self.provider) {
      self.viewer.imageryLayers.remove(self.provider, true)
      self.provider.show = false
    }
    /* let self = this;
        window.setTimeout(() => {
            if (self.provider) {
                self.viewer.imageryLayers.remove(self.provider, true);
                self.provider.show = false;
            }
        }, 1000); */
  }
}

export default VectorTileLayer
