<script>
import commonMixin from '@/base/mixins/common.js'
import $ from 'jquery'
import { generateID, addOverLay, gerOverLay, removeOverLay } from '@/base/util.js'
export default {
  name: 'bs-measure',
  mixins: [commonMixin('interaction')],
  render() { },
  data() {
    return {
      sketch: null,
      helpTooltipElement: null,
      helpTooltip: null,
      measureTooltipElement: null,
      measureTooltip: null,
      continuePolygonMsg: '单击继续绘制多边形,双击结束绘制',
      continueLineMsg: '单击继续绘制线,双击结束绘制',
      wgs84Sphere: null,
      counter: 0,
      output: '',
      styles: [],
      measureClickTooltips: [],
      disableClick: true,
      disableMouseOver: true,
      listener: null,
      mouseMoveListener: null,
      clickListener: null,
      unique: generateID()
    }
  },
  props: {
    type: {
      type: String
    },
    id: { type: String },
    name: { type: String },
    actived: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    actived(flag) {
      this.originInstance.setActive(flag)
      if (flag) {
        this.unique = generateID()
        this.disableClick = true
        this.disableMouseOver = true
        this.counter = 0
        this.measureClickTooltips = []
      } else {
        if (this.disableMouseOver) {
          this.doubleMouseEvt()
        }
        this.disableClick = false
        this.disableMouseOver = false
      }
    }
  },
  methods: {
    load() {
      const { ol, $rootComponent, id, name, continuePolygonMsg, continueLineMsg } = this
      var vector = $rootComponent.addLayer({ id, name })
      this.styles = [
        new ol.style.Style({ // 图层样式
          fill: new ol.style.Fill({
            color: 'rgba(255, 255, 255, 0.2)' // 填充颜色
          }),
          stroke: new ol.style.Stroke({
            color: '#ffcc33', // 边框颜色
            width: 2 // 边框宽度
          }),
          image: new ol.style.Circle({
            radius: 5,
            fill: new ol.style.Fill({
              color: 'orange'
            })
          })
        }),
        new ol.style.Style({
          image: new ol.style.Circle({
            radius: 5,
            fill: new ol.style.Fill({
              color: 'orange'
            })
          }),
          geometry: function (feature) {
            var coordinates = feature.getGeometry().getCoordinates()
            return new ol.geom.MultiPoint(coordinates)
          }
        })
      ]
      this.wgs84Sphere = new ol.Sphere(6378137)
      vector.setStyle(this.styles)
      this.mouseMoveListener = $rootComponent.$on('mousemove', (evt) => {
        if (this.disableMouseOver) {
          if (evt.dragging) {
            return
          }
          /** @type {string} */
          var helpMsg = '单击开始绘制'
          // 判断绘制几何类型设置相应的帮助提示信息
          if (this.sketch) {
            var geom = (this.sketch.getGeometry())
            if (geom instanceof ol.geom.Polygon) {
              helpMsg = continuePolygonMsg // 绘制多边形时提示相应内容
            } else if (geom instanceof ol.geom.LineString) {
              helpMsg = continueLineMsg // 绘制线时提示相应内容
            }
          }
          if (this.actived) {
            this.helpTooltipElement.innerHTML = helpMsg // 将提示信息设置到对话框中显示
            this.helpTooltip.setPosition([evt.lon, evt.lat]) // 设置帮助提示框的位置
          }
          // $(helpTooltipElement).removeClass('hidden') // 移除帮助提示框的隐藏样式进行显示
          $($rootComponent.getViewport()).on('mouseout', function () {
            // $(helpTooltipElement).addClass('hidden')
          })
        }
      })
      this.clickListener = $rootComponent.$on('singleclick', (evt) => {
        if (this.disableClick) {
          var content = this.output
          var border = '1px solid red'
          if (this.counter === 0) {
            this.counter++
            content = '起点'
            border = '1px solid green'
          }
          const pos = [evt.lon, evt.lat]
          const elem = document.createElement('div')
          elem.style.background = '#fff'
          elem.style.border = border
          elem.style.color = '#333'
          elem.style.fontSize = '12px'
          elem.style.fontFamily = '宋体,Simsun'
          elem.style.paddingLeft = '3px'
          elem.style.borderRadius = '4px'
          elem.innerHTML = content
          let overlay = new ol.Overlay({
            element: elem,
            offset: [7, 0],
            positioning: 'center-left'
          })
          overlay.setPosition(pos)
          $rootComponent.addOverlay(overlay)
          this.measureClickTooltips.push(overlay)
        }
      })
      this.addInteraction()
    },
    addInteraction() {
      const { type, ol, $rootComponent, id, styles } = this
      const source = $rootComponent.getLayer(id).getSource()
      this.originInstance = new ol.interaction.Draw({
        source: source, // 测量绘制层数据源
        type: /** @type {ol.geom.GeometryType} */ (type), // 几何图形类型
        style: styles
      })
      $rootComponent.addInteraction(this.originInstance, this.actived)
      this.createMeasureTooltip() // 创建测量工具提示框
      this.createHelpTooltip() // 创建帮助提示框
      // var listener = null
      // 绑定交互绘制工具开始绘制的事件
      this.originInstance.on('drawstart', (evt) => {
        // set sketch
        this.sketch = evt.feature // 绘制的要素
        /** @type {ol.Coordinate|undefined} */
        var tooltipCoord = evt.coordinate // 绘制的坐标
        // 绑定change事件，根据绘制几何类型得到测量长度值或面积值，并将其设置到测量工具提示框中显示
        this.listener = this.sketch.getGeometry().on('change', (evt) => {
          var geom = evt.target // 绘制几何要素
          if (geom instanceof ol.geom.Polygon) {
            this.output = this.formatArea(/** @type {ol.geom.Polygon} */(geom)) // 面积值
            tooltipCoord = geom.getInteriorPoint().getCoordinates() // 坐标
          } else if (geom instanceof ol.geom.LineString) {
            this.output = this.formatLength(/** @type {ol.geom.LineString} */(geom)) // 长度值
            tooltipCoord = geom.getLastCoordinate() // 坐标
          }
          this.measureTooltipElement.innerHTML = this.output // 将测量值设置到测量工具提示框中显示
          this.measureTooltip.setPosition(tooltipCoord) // 设置测量工具提示框的显示位置
        })
      })
      // 绑定交互绘制工具结束绘制的事件
      this.originInstance.on('drawend', (evt) => {
        const { ol, $rootComponent, id } = this
        const pos = this.measureTooltip.getPosition()
        this.measureTooltip.setPosition(undefined)
        this.helpTooltip.setPosition(undefined)
        this.measureTooltipElement.className = 'tooltip tooltip-static' // 设置测量提示框的样式
        this.measureTooltip.setOffset([0, -7])
        this.sketch = null // 置空当前绘制的要素对象
        this.measureTooltipElement = null // 置空测量工具提示框对象
        this.createMeasureTooltip() // 重新创建一个测试工具提示框显示结果
        ol.Observable.unByKey(this.listener)
        ol.Observable.unByKey(this.mouseMoveListener)
        ol.Observable.unByKey(this.clickListener)
        this.counter = 0
        const contaner = document.createElement('div')
        const span = document.createElement('span')
        contaner.style.background = '#fff'
        contaner.style.border = ' 1px solid red'
        contaner.style.color = '#333'
        contaner.style.fontSize = '12px'
        contaner.style.fontFamily = '宋体,Simsun'
        contaner.style.paddingLeft = '3px'
        contaner.style.borderRadius = '4px'
        const a = document.createElement('a')
        a.style.border = '1px solid rgb(255, 1, 3)'
        a.style.background = '#ffffff'
        a.style.width = '15px'
        a.style.height = '18px'
        a.style.marginLeft = '5px'
        a.style.marginRight = '3px'
        a.style.cursor = 'hand'
        a.innerHTML = '✖'
        span.innerHTML = '总长度为：' + this.output
        contaner.appendChild(span)
        contaner.appendChild(a)
        let overlay = new ol.Overlay({
          element: contaner,
          offset: [7, 0],
          positioning: 'center-left'
        })
        overlay.setPosition([...pos])
        $rootComponent.addOverlay(overlay)
        this.measureClickTooltips.push(overlay)
        addOverLay(this.unique, [...this.measureClickTooltips])
        this.disableClick = false
        this.disableMouseOver = false
        this.originInstance.setActive(false)
        this.$emit('update:actived', false)
        a.onclick = ((attr, feature) => {
          return (e) => {
            $rootComponent.getLayer(id).getSource().removeFeature(feature)
            const overlays = gerOverLay(attr)
            for (var info of overlays) {
              $rootComponent.removeOverlay(info)
            }
            removeOverLay(attr)
          }
        })(this.unique, evt.feature)
      })
    },
    // 开启测距，没有双击就关闭测量控件
    doubleMouseEvt() {
      const { ol, $rootComponent } = this
      this.measureTooltip.setPosition(undefined)
      this.helpTooltip.setPosition(undefined)
      this.sketch = null // 置空当前绘制的要素对象
      this.measureTooltipElement = null // 置空测量工具提示框对象
      this.createMeasureTooltip() // 重新创建一个测试工具提示框显示结果
      ol.Observable.unByKey(this.listener)
      ol.Observable.unByKey(this.mouseMoveListener)
      ol.Observable.unByKey(this.clickListener)
      this.disableClick = false
      this.disableMouseOver = false
      this.originInstance.setActive(false)
      this.$emit('update:actived', false)
      this.measureClickTooltips.forEach(element => {
        $rootComponent.removeOverlay(element)
      })
      this.measureClickTooltips = []
    },
    createHelpTooltip() {
      const { ol, $rootComponent } = this
      if (this.helpTooltipElement) {
        this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement)
      }
      this.helpTooltipElement = document.createElement('div')
      this.helpTooltipElement.style.background = '#fff'
      this.helpTooltipElement.style.border = ' 1px solid red'
      this.helpTooltipElement.style.color = '#333'
      this.helpTooltipElement.style.fontSize = '12px'
      this.helpTooltipElement.style.fontFamily = '宋体,Simsun'
      this.helpTooltipElement.style.borderRadius = '4px'
      this.helpTooltip = new ol.Overlay({
        element: this.helpTooltipElement,
        offset: [7, 0],
        positioning: 'center-left'
      })
      $rootComponent.addOverlay(this.helpTooltip)
    },
    createMeasureTooltip() {
      const { ol, $rootComponent } = this
      if (this.measureTooltipElement) {
        this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement)
      }
      this.measureTooltipElement = document.createElement('div')
      this.measureTooltipElement.style.background = '#fff'
      this.measureTooltipElement.style.border = ' 1px solid red'
      this.measureTooltipElement.style.color = '#333'
      this.measureTooltipElement.style.fontSize = '12px'
      this.measureTooltipElement.style.fontFamily = '宋体,Simsun'
      this.measureTooltipElement.style.borderRadius = '4px'
      this.measureTooltip = new ol.Overlay({
        element: this.measureTooltipElement,
        offset: [0, -15],
        positioning: 'bottom-center'
      })
      $rootComponent.addOverlay(this.measureTooltip)
    },
    formatLength(line) {
      var coordinates = line.getCoordinates() // 解析线的坐标
      var length = 0
      const { ol, $rootComponent } = this
      var sourceProj = $rootComponent.getView().getProjection()
      // 通过遍历坐标计算两点之前距离，进而得到整条线的长度
      for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
        var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326')
        var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326')
        length += this.wgs84Sphere.haversineDistance(c1, c2)
      }
      var output = ''
      if (length > 100) {
        output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km' // 换算成KM单位
      } else {
        output = (Math.round(length * 100) / 100) + ' ' + 'm' // m为单位
      }
      return output // 返回线的长度
    },
    formatArea(polygon) {
      const { $rootComponent } = this
      var sourceProj = $rootComponent.getView().getProjection()
      var geom = /** @type {ol.geom.Polygon} */ (polygon.clone().transform(sourceProj, 'EPSG:4326'))
      var coordinates = geom.getLinearRing(0).getCoordinates() // 解析多边形的坐标值
      var area = Math.abs(this.wgs84Sphere.geodesicArea(coordinates))
      var output = ''
      if (area > 10000) {
        output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>'// 换算成KM单位
      } else {
        output = (Math.round(area * 100) / 100) + ' ' + 'm<sup>2</sup>'// m为单位
      }
      return output
    }
  }
}
</script>
 <style scoped>
</style>
