<template>
  <!-- leaflet 地图组件，内嵌于页面中
      功能： 支持手动绘制区域、编辑区域、删除区域，以及渲染 geoJson 面图
   -->
  <div class="map-box">
    <div :id="id" :style="{ width, height }" />
    <div v-show="isShowClearBtn" @click="clearAreaLayer()" class="button" title="删除已保存的区域">
      <a-icon type="delete" />
    </div>
  </div>
</template>
<script>
import * as L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import 'proj4leaflet'
import 'leaflet.chinatmsproviders'
import '@/assets/map/leaflet.ChineseTmsProviders'
import 'leaflet-draw'
export default {
  name: 'TxMap',
  props: {
    id: {
      type: String,
      default: () => ''
    },
    width: {
      type: String,
      default: () => '100%'
    },
    height: {
      type: String,
      default: () => '280px'
    },
    center: {
      type: Object,
      default: () => {
        return {
          latitude: '36.70261',
          longitude: '119.16160'
        }
      }
    },
    geoJson: {
      type: String,
      default: () => ''
    },
    // 操作类型： add-新增  edit-编辑
    operateType: {
      type: String,
      default: () => ''
    },
    visible: {
      type: Boolean,
      default: () => false
    }
  },
  data() {
    return {
      isShowClearBtn: false,
      // L.map 对象
      map: null,
      // L.Control.Draw 控件对象
      drawControl: null,
      // 图形图层组
      drawLayerGroup: null
    }
  },
  watch: {
    visible(newVal) {
      if (newVal) {
        if (this.isAdd()) {
          // 新增
          this.init()
          this.clearAreaLayer()
        } else if (this.isEdit()) {
          // 编辑
          this.init()
          this.addLayers(this.geoJson)
        } else {
          // 查看详情，没有绘图控件
          this.init('noControl')
          this.addLayers(this.geoJson)
        }
        this.handleClearBtn()
      }
    }
  },
  mounted() {
    if (this.isDetail()) {
      this.init('noControl')
    } else {
      this.init()
    }

    this.handleClearBtn()

    this.addLayers(this.geoJson)
  },
  methods: {
    init(data) {
      // 初始化地图
      this.initMap()
      if (data !== 'noControl') {
        // 初始化绘制控件
        this.initDrawCtrl()
      }
    },

    initMap() {
      const { latitude, longitude } = this.center
      if (!this.map) {
        this.map = L.map(document.getElementById(this.id), {
          center: [latitude || '36.70261', longitude || '119.16160'],
          zoom: 9,
          //不添加属性说明控件
          attributionControl: false
        })
      }

      this.tileLayer = [
        L.tileLayer.chinaProvider('GaoDe.Normal.Map', {
          maxZoom: 16,
          minZoom: 4
        })
      ]

      this.tileLayer.map((layer) => {
        this.map.addLayer(layer)
      })
    },

    handleClearBtn() {
      if (this.isAdd() || this.isDetail()) {
        this.isShowClearBtn = false
      } else {
        if (this.hasGeoJson()) {
          this.isShowClearBtn = true
        } else {
          this.isShowClearBtn = false
        }
      }
    },

    // 初始化绘制控件
    initDrawCtrl() {
      // 判断当前没有图层组，需先添加
      if (!this.drawLayerGroup) {
        //图层组
        this.drawLayerGroup = new L.FeatureGroup()
      }

      if (!this.map.hasLayer(this.drawLayerGroup)) {
        // 添加
        this.map.addLayer(this.drawLayerGroup)
      }

      // 初始化绘制控件
      if (!this.drawControl) {
        this.initDrawTooltip()
        this.drawControl = new L.Control.Draw({
          position: 'topleft', // 控件位置 'topleft'(默认), 'topright', 'bottomleft' or 'bottomright'
          draw: {
            polygon: true,
            polyline: false,
            rectangle: false,
            circle: false,
            marker: false,
            circlemarker: false
          },
          edit: {
            // 绘制图层
            featureGroup: this.drawLayerGroup,
            // 图形编辑控件
            edit: true,
            // 图形删除控件
            remove: true
          }
        }).addTo(this.map) // 要添加到 L.map 对象中

        this.Edit = new L.EditToolbar.Edit(this.map, { featureGroup: this.drawLayerGroup })

        this.Delete = new L.EditToolbar.Delete(this.map, { featureGroup: this.drawLayerGroup })
      }

      // 添加绘制完监听事件
      this.map.on(L.Draw.Event.CREATED, this.drawCreatedBack)
      // 删除事件
      this.map.on(L.Draw.Event.DELETED, this.handleDelete)
      // 编辑事件
      this.map.on(L.Draw.Event.EDITED, this.handleEdited)
    },

    // 交互绘制回调
    drawCreatedBack(e) {
      // 绘制的图形图层对象
      let drawLayer = e.layer

      // 添加到图层组
      this.drawLayerGroup.addLayer(drawLayer)

      let { lat, lng } = drawLayer.getCenter()
      lat = parseFloat(lat).toFixed(5)
      lng = parseFloat(lng).toFixed(5)
      // 更新中心点坐标
      this.$emit('submitCenterMarker', lat, lng)

      this.$emit('submitLatlngs', this.drawLayerGroup._layers, this.isHasAreaLayer())
    },

    handleDelete() {
      this.$emit('submitLatlngs', this.drawLayerGroup._layers, this.isHasAreaLayer())
    },

    handleEdited() {
      this.$emit('submitLatlngs', this.drawLayerGroup._layers, this.isHasAreaLayer())
    },

    isHasAreaLayer() {
      let flag
      if (this.areaLayer) {
        flag = this.map.hasLayer(this.areaLayer)
      } else {
        flag = false
      }
      return flag
    },

    // 改变绘制控件的按钮文本及提示语
    initDrawTooltip() {
      L.drawLocal.draw.handlers.polygon = {
        tooltip: {
          start: '点击地图开始绘制多边形',
          cont: '继续选择',
          end: '点击第一个顶点完成绘制'
        }
      }
      L.drawLocal.draw.toolbar.buttons.polygon = '绘制'
      L.drawLocal.edit.toolbar.actions.save.text = '保存'
      L.drawLocal.edit.toolbar.actions.save.title = '保存'
      L.drawLocal.edit.toolbar.actions.cancel.text = '取消'
      L.drawLocal.edit.toolbar.actions.cancel.title = '取消'
      L.drawLocal.edit.toolbar.actions.clearAll.text = '清除全部'
      L.drawLocal.edit.toolbar.actions.clearAll.title = '清除全部'
      L.drawLocal.edit.toolbar.buttons.editDisabled = '暂无区域可编辑'
      L.drawLocal.edit.toolbar.buttons.removeDisabled = '暂无区域可删除'
      L.drawLocal.edit.handlers.remove.tooltip.text = '选中一个区域去清除'
      L.drawLocal.edit.toolbar.buttons.edit = '编辑'
      L.drawLocal.edit.toolbar.buttons.remove = '删除'
      L.drawLocal.edit.toolbar.buttons.cancel = '取消'
      L.drawLocal.edit.toolbar.buttons.save = '保存'
      L.drawLocal.draw.toolbar.actions.text = '取消'
      L.drawLocal.draw.toolbar.actions.title = '取消绘制'
      L.drawLocal.draw.toolbar.finish.text = '完成'
      L.drawLocal.draw.toolbar.finish.title = '完成绘制'
      L.drawLocal.draw.toolbar.undo.text = '撤销'
      L.drawLocal.draw.toolbar.undo.title = '撤销'
      L.drawLocal.edit.handlers.edit.tooltip.subtext = '点击取消以撤消更改'
      L.drawLocal.edit.handlers.edit.tooltip.text = '拖动标记以编辑图形'
    },

    // 销毁地图以及绘制控件
    destroyDrawCtrl() {
      // 移除地图上的控制组件
      if (this.drawControl) {
        this.map.removeControl(this.drawControl)
      }
      // L.Control.Draw 控件对象
      this.drawControl = null
      // 删除全部绘制的图层
      if (this.drawLayerGroup) {
        this.drawLayerGroup.clearLayers()
      }
      // 移除已保存的区域
      if (this.map.hasLayer(this.areaLayer)) {
        this.map.removeLayer(this.areaLayer)
      }

      // 取消监听事件，避免其它地方也监听了 CREATED 事件
      this.map.off(L.Draw.Event.CREATED, this.drawCreatedBack)
      this.map.off(L.Draw.Event.DELETED, this.handleDelete)
      this.map.off(L.Draw.Event.EDITED, this.handleEdited)
      // 销毁该地图
      this.map.remove()
      this.map = null
    },

    addLayers(geoJson) {
      if (this.hasGeoJson()) {
        this.areaLayer = L.geoJSON(JSON.parse(geoJson), {
          style: (feature) => {
            return {
              fillOpacity: 0.3,
              weight: 2,
              fillColor: '#40a9ff'
            }
          }
        })

        if (!this.map.hasLayer(this.areaLayer)) {
          this.map.addLayer(this.areaLayer)
        }

        this.map.fitBounds(this.areaLayer.getBounds())

        // this.Delete.options.featureGroup._layers = this.areaLayer._layers
        // this.Edit.options.featureGroup._layers = this.areaLayer._layers
        // this.map.removeControl(this.drawControl)
        // L.Control.Draw 控件对象
        // this.drawControl = null
        // this.initDrawCtrl()
      }
    },

    hasGeoJson() {
      return (
        this.geoJson &&
        this.geoJson.length > 0 &&
        JSON.parse(this.geoJson).features &&
        JSON.parse(this.geoJson).features.length > 0
      )
    },

    // 删除已保存的区域
    clearAreaLayer() {
      if (this.map.hasLayer(this.areaLayer)) [this.map.removeLayer(this.areaLayer)]
      this.isShowClearBtn = false
      this.$emit('submitLatlngs', [], false)
    },

    isAdd() {
      return this.operateType === 'add'
    },

    isEdit() {
      return this.operateType === 'edit'
    },

    isDetail() {
      return this.operateType === 'detail'
    }
  }
}
</script>

<style scoped lang="scss">
@import '~leaflet-draw/dist/leaflet.draw.css';
  .map-box {
    width: auto;
    height: auto;
    position: relative;
  }
  .button {
    position: absolute;
    top: 203px;
    left: 10px;
    z-index: 1001;
    width: 34px;
    padding: 0;
    height: 30px;
    background: #ffffff;
    line-height: 30px;
    text-align: center;
    border: 1px solid #a79f9f;
    border-radius: 3px;
    cursor: pointer;
    &:hover {
      background: #efefef;
    }
  }
  ::v-deep .ant-btn:hover,
  ::v-deep .ant-btn:focus {
    color: rgba(0, 0, 0, 0.65);
    ">#fff;
  }
</style>