<template>
  <div>
    <el-button
      v-show="drawShow"
      type="primary"
      icon="el-icon-edit-outline"
      size="mini"
      @click.prevent="drawGeometry"
      style="margin-left: 20px; margin-bottom: 10px"
    >
      绘制图形
    </el-button>

    <el-select
      v-show="selectShow"
      v-model="drawMode"
      clearable
      size="small"
      placeholder="请选择形状"
      class="filter-item"
      style="width: 280px"
      @change="changeShape"
    >
      <el-option
        v-for="item of shapeOptions"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <div :id="mapDivId" style="height: 700px"></div>
  </div>
</template>
<!--
数据结构
v-model, background
{
  geometries: [{
    type: 'Point',//必填
    points: [{ x: 0, y: 0 }],//必填，根据图形决定个数
    symbol: {},//选填，不填根据symbols的值使用默认值
    radius: 0,//选填，图形为圆形时必填
    width: 0, //选填，图形为矩形或者椭圆形时必填
    height: 0,//选填，图形为矩形或者椭圆形时必填
    infoWindow: {
      title: '',
      width: 150,
      content: '',
    },//选填，不填没有弹出窗
    openInfoWindow: true,//选填
  }]//必填
}
symbols//设定各个图形的默认样式
{
  Point:{},
  Polygon:{},
  Circle: {},
  Ellipse: {},
  Rectangle: {}
}
-->
<script>
import 'maptalks/dist/maptalks.css'
import * as maptalks from 'maptalks'

export default {
  props: {
    value: {
      type: Array,
      require: true,
      default: () => [],
    },
    symbols: {
      type: Object,
      default: () => {
        return {
          Point: null,
          LineString: {
            lineColor: 'rgb(0,196,240)',
            lineWidth: 2,
            lineOpacity: 1,
          },
          Polygon: {
            lineColor: 'rgb(0,196,240)',
            lineWidth: 2,
            lineOpacity: 1,
            polygonFill: 'rgb(135,196,240)',
            polygonOpacity: 0.6,
            textName: '',
            textSize: 18,
            textFill: '#eb4848',
          },
          Circle: {
            lineColor: 'rgb(0,196,240)',
            lineWidth: 2,
            lineOpacity: 1,
            polygonFill: 'rgb(135,196,240)',
            polygonOpacity: 0.6,
          },
          Ellipse: {
            lineColor: 'rgb(0,196,240)',
            lineWidth: 2,
            lineOpacity: 1,
            polygonFill: 'rgb(135,196,240)',
            polygonOpacity: 0.6,
          },
          Rectangle: {
            lineColor: 'rgb(0,196,240)',
            lineWidth: 2,
            lineOpacity: 1,
            polygonFill: 'rgb(135,196,240)',
            polygonOpacity: 0.6,
          },
        }
      },
    },
    background: {
      type: Array,
      default: () => [],
    },
    drawShow: {
      type: Boolean,
      default: false,
    },
    selectShow: {
      type: Boolean,
      default: false,
    },
    lineLengthShow: {
      type: Boolean,
      default: false,
    },
    drawMode: {
      type: String,
      default: 'Point',
    },
  },
  data() {
    return {
      mapDivId: '',
      locationData: null,
      gpsConfig: null,
      baseExtent: null,
      
      map: null,
      mapLayer: null,
      geometryLayer: null,
      backgroundLayer: null,
      foregroundLayer: null,
      drawTool: null,

      shapeOptions: [
        { label: '点', value: 0, shapeType: 'marker', mode: 'Point', max: 1, min: 1 },
        { label: '线', value: 1, shapeType: 'line', mode: 'LineString', max: 999, min: 2 },
        { label: '矩形', value: 2, shapeType: 'rectangle', mode: 'Rectangle', max: 4, min: 4 },
        { label: '圆形', value: 3, shapeType: 'round', mode: 'Circle', max: 1, min: 1 },
        { label: '椭圆', value: 4, shapeType: 'round2', mode: 'Ellipse', max: 1, min: 1 },
        { label: '多边形', value: 5, shapeType: 'polygon', mode: 'Polygon', max: 999, min: 3 },
      ],
      drawToolOption: [
        'Point',
        'LineString',
        'Polygon',
        'Circle',
        'Ellipse',
        'Rectangle',
        'FreeHandLineString',
        'FreeHandPolygon',
      ],
    }
  },
  created() {
    this.mapDivId = Math.random().toString(16)
  },
  mounted() {
    this.getLocationData()
  },
  watch: {
    value(newValue, oldValue) {
      this.refreshGeometry()
    },
    background(newValue, oldValue) {
      this.refreshGeometry()
    },
  },
  methods: {
    getLocationData() {
      this.locationData = this.$setting
      if (this.locationData) {
        this.gpsConfig = this.locationData.GPSConfig

        this.baseExtent = new maptalks.Extent(
          this.gpsConfig.Coordinate0,
          this.gpsConfig.Coordinate1,
        )

        this.createMap()
        // console.log(pointList);
      } else {
        console.log('获取定位配置文件失败')
      }
    },
    createMap() {
      if (this.map) this.map.remove()
      let _this = this
      this.map = new maptalks.Map(this.mapDivId, {
        center: this.baseExtent.getCenter(),
        //centerCross: true,
        zoom: this.gpsConfig.MapZoom,
        maxZoom: this.gpsConfig.MapMaxZoom,
        minZoom: this.gpsConfig.MapMinZoom,
        bearing: this.gpsConfig.MapBearing,
        pitch: this.gpsConfig.MapPitch,
        dragRotate: false,
        maxExtent: this.baseExtent,
        zoomControl: {
          position: 'top-left',
          slider: false,
          zoomLevel: false,
        },
        attribution: {
          content: '',
        },
        spatialReference: {
          projection: this.gpsConfig.Projection,
          resolutions: (function () {
            const resolutions = []
            for (let i = 0; i <= _this.gpsConfig.ResolutionMax; i++) {
              resolutions[i] = _this.gpsConfig.Resolution0 / Math.pow(2, i)
            }
            return resolutions
          })(),
        },
        baseLayer: new maptalks.TileLayer('base', this.locationData.MapBaseLayer)
      })
      //将地图设置为适合给定范围的最大缩放级别
      this.map.fitExtent(this.baseExtent, 0)
      // 图形图层
      this.geometryLayer = new maptalks.VectorLayer('geometry', {
        zIndex: 10,
        visible: true,
        forceRenderOnMoving: true,
        forceRenderOnZooming: true,
        forceRenderOnRotating: true,
      }).addTo(this.map)
      // 背景图层
      this.backgroundLayer = new maptalks.VectorLayer('background', {
        zIndex: 1,
        visible: true,
        forceRenderOnMoving: true,
        forceRenderOnZooming: true,
        forceRenderOnRotating: true,
      }).addTo(this.map)
      // 前景图层
      this.foregroundLayer = new maptalks.VectorLayer('foreground', {
        zIndex: 20,
        visible: true,
        forceRenderOnMoving: true,
        forceRenderOnZooming: true,
        forceRenderOnRotating: true,
      }).addTo(this.map)

      this.drawTool = new maptalks.DrawTool({
        mode: 'Polygon',
        once: true,
      })
        .addTo(this.map)
        .disable()

      this.drawTool.on('drawend', (param) => {
        // console.log(param)
        this.geometryLayer.addGeometry(param.geometry)
        let gs = []
        let geometries = this.geometryLayer.getGeometries()
        if (geometries) {
          geometries.forEach((geometry) => {
            if (geometry instanceof maptalks.Marker) {
              gs.push({
                type: 'Point',
                points: [geometry.getCoordinates()],
              })
              return true
            }
            if (geometry instanceof maptalks.LineString) {
              gs.push({
                type: 'LineString',
                points: geometry.getCoordinates(),
              })
              if (this.lineLengthShow) {
                this.addLineLength(geometry.getCoordinates())
              }
              return true
            }
            if (geometry instanceof maptalks.Polygon) {
              gs.push({
                type: 'Polygon',
                points: geometry.getCoordinates()[0],
              })
              return true
            }
            if (geometry instanceof maptalks.Circle) {
              gs.push({
                type: 'Circle',
                points: [geometry.getCoordinates()],
                radius: geometry.getRadius(),
              })
              return true
            }
            if (geometry instanceof maptalks.Ellipse) {
              gs.push({
                type: 'Ellipse',
                points: [geometry.getCoordinates()],
                width: geometry.getWidth(),
                height: geometry.getHeight(),
              })
              return true
            }
            if (geometry instanceof maptalks.Rectangle) {
              gs.push({
                type: 'Rectangle',
                points: [geometry.getCoordinates()],
                width: geometry.getWidth(),
                height: geometry.getHeight(),
              })
              return true
            }
          })
        }
        this.$emit('input', [
          { geometries: gs },
        ])
      })
      //右上角工具栏
      new maptalks.control.Toolbar({
        items: [
          {
            item: '复位地图',
            click: function () {
              _this.map.animateTo(
                {
                  //center: baseRelativeExtent.getCenter(),
                  // zoom: 13,
                  bearing: _this.gpsConfig.MapBearing,
                  pitch: _this.gpsConfig.MapPitch,
                },
                {
                  duration: 1000,
                },
                (frame) => {
                  if (frame.state.playState === 'finished') {
                    _this.map.fitExtent(_this.baseExtent, 0, {
                      duration: 1000,
                    })
                  }
                }
              )
            },
          },
        ],
      }).addTo(this.map)

      this.refreshGeometry()
    },
    setDrawTool() {
      // console.log(mode)
      this.drawTool.setMode(this.drawMode) //选择绘画工具的模式

      this.drawTool.setSymbol(this.symbols[this.drawMode])

      // if (this.drawMode != 'Point') {
      //   drawTool.setSymbol(this.symbols[this.drawMode])
      // } else {
      //   // 从其他模式切换成点后，需要删除symbol属性，否则无法正常切换
      //   if (drawTool.options.hasOwnProperty('symbol')) {
      //     delete drawTool.options.symbol
      //   }
      // }
      this.drawTool.enable()
      // console.log(drawTool)
    },
    drawGeometry() {
      this.geometryLayer.clear()
      this.foregroundLayer.clear()
      this.setDrawTool()
    },
    refreshGeometry() {
      this.geometryLayer.clear()
      this.foregroundLayer.clear()
      this.backgroundLayer.clear()

      if (this.value && this.value.length > 0)
        this.value.forEach((a) => this.addDataGeometry(a.geometries))

      if (this.background && this.background.length > 0)
        this.background.forEach((a) => this.addBackgroundGeometry(a.geometries))
    },
    addDataGeometry(geometries) {
      geometries.forEach((it, i) => {
        if (it.type) {
          switch (it.type) {
            case 'Point':
              let point = new maptalks.Marker(it.points[0], {
                symbol: it.symbol || this.symbols[it.type],
              }).addTo(this.geometryLayer)
              if (it.infoWindow) point.setInfoWindow(it.infoWindow)
              if (it.openInfoWindow) point.openInfoWindow()
              break
            case 'LineString':
              let line = new maptalks.LineString(
                it.points,
                { symbol: it.symbol || this.symbols[it.type] }
              ).addTo(this.geometryLayer)
              if (it.infoWindow) line.setInfoWindow(it.infoWindow)
              if (it.openInfoWindow) line.openInfoWindow()
              if (this.lineLengthShow) {
                this.addLineLength(it.points)
              }
              break
            case 'Polygon':
              if (it.mark) {
                //console.log(it.mark)
                this.symbols[it.type].textName = it.mark
              }
              let polygon = new maptalks.Polygon(
                it.points,
                { symbol: it.symbol || this.symbols[it.type] }
              ).addTo(this.geometryLayer)
              if (it.infoWindow) polygon.setInfoWindow(it.infoWindow)
              if (it.openInfoWindow) polygon.openInfoWindow()
              break
            case 'Circle':
              let circle = new maptalks.Circle(it.points[0], it.radius, {
                symbol: it.symbol || this.symbols[it.type],
              }).addTo(this.geometryLayer)
              if (it.infoWindow) circle.setInfoWindow(it.infoWindow)
              if (it.openInfoWindow) circle.openInfoWindow()
              break
            case 'Ellipse':
              let ellipse = new maptalks.Ellipse(
                it.points[0],
                it.width,
                it.height,
                {
                  symbol: it.symbol || this.symbols[it.type],
                }
              ).addTo(this.geometryLayer)
              if (it.infoWindow) ellipse.setInfoWindow(it.infoWindow)
              if (it.openInfoWindow) ellipse.openInfoWindow()
              break
            case 'Rectangle':
              let rectangle = new maptalks.Polygon(
                it.points[0],
                it.width,
                it.height,
                {
                  symbol: it.symbol || this.symbols[it.type],
                }
              ).addTo(this.geometryLayer)
              if (it.infoWindow) rectangle.setInfoWindow(it.infoWindow)
              if (it.openInfoWindow) rectangle.openInfoWindow()
              break
          }
        }
      })
    },
    addBackgroundGeometry(geometries) {
      geometries.forEach((it, i) => {
        if (it.type) {
          switch (it.type) {
            case 'Point':
              let point = new maptalks.Marker(it.points[0], {
                symbol: it.symbol || this.symbols[it.type],
              }).addTo(this.backgroundLayer)
              if (it.infoWindow) point.setInfoWindow(it.infoWindow)
              break
            case 'LineString':
              let line = new maptalks.LineString(
                it.points,
                { symbol: it.symbol || this.symbols[it.type] }
              ).addTo(this.backgroundLayer)
              if (it.infoWindow) line.setInfoWindow(it.infoWindow)
              break
            case 'Polygon':
              let polygon = new maptalks.Polygon(
                it.points,
                { symbol: it.symbol || this.symbols[it.type] }
              ).addTo(this.backgroundLayer)
              if (it.infoWindow) polygon.setInfoWindow(it.infoWindow)
              break
            case 'Circle':
              console.log(it)
              let circle = new maptalks.Circle(it.points[0], it.radius, {
                symbol: it.symbol || this.symbols[it.type],
              }).addTo(this.backgroundLayer)
              if (it.infoWindow) circle.setInfoWindow(it.infoWindow)
              break
            case 'Ellipse':
              let ellipse = new maptalks.Ellipse(
                it.points[0],
                it.width,
                it.height,
                {
                  symbol: it.symbol || this.symbols[it.type],
                }
              ).addTo(this.backgroundLayer)
              if (it.infoWindow) ellipse.setInfoWindow(it.infoWindow)
              break
            case 'Rectangle':
              let rectangle = new maptalks.Polygon(
                it.points[0],
                it.width,
                it.height,
                {
                  symbol: it.symbols || this.symbols[it.type],
                }
              ).addTo(this.backgroundLayer)
              if (it.infoWindow) rectangle.setInfoWindow(it.infoWindow)
              break
          }
        }
      })
    },

    //清除图形图层
    changeShape() {
      this.geometryLayer.clear()
      this.foregroundLayer.clear()
      // console.log(this.shapeType);
    },

    addLineLength(points) {
      if (points && points.length > 1) {
        for (let i = 0; i < points.length - 1; i++) {
          let d = this.map.computeLength(points[i], points[i + 1])
          let c = new maptalks.LineString([points[i], points[i + 1]]).getCenter()
          this.foregroundLayer.addGeometry(
            new maptalks.Marker(c, {
              symbol: {
                textName: (d / 1000).toFixed(3) + '米',
                textSize: 10,
              },
            })
          )
        }
      }
    },
  },
}
</script>

<style lang="scss" scoped>
</style>
             