<template>
  <section class="AiMap" :class="{mask}">
    <div ref="amap" class="map"/>
    <div v-if="mask" class="mask"/>
    <slot/>
  </section>
</template>

<script>
import AMapLoader from "@amap/amap-jsapi-loader";

export default {
  name: "AiMap",
  props: {
    plugins: {default: () => ['AMap.DistrictSearch', 'AMap.LineSearch']},
    map: Object,
    lib: Object,
    mapStyle: String,
    areaId: String,
    is3d: Boolean,
    ops: {default: () => ({})},
    markers: {default: () => []},
    mask: Boolean,
    searchBus: {default: "2"},
    pulseLines: Boolean,
    onlyShowArea: Boolean,
    satellite: Boolean
  },
  data() {
    return {
      amap: null,
      mapLib: null,
      loca: null,
    }
  },
  watch: {
    markers: {
      deep: true, handler() {
        this.addMarkers()
      }
    }
  },
  methods: {
    initMap(c = 0) {
      let {plugins, mapStyle} = this
      AMapLoader.load({
        key: '54a02a43d9828a8f9cd4f26fe281e74e',
        version: '2.0',
        plugins,
        Loca: {version: '2.0.0'}
      }).then(AMap => {
        this.mapLib = AMap
        this.$emit('update:lib', AMap)
        if (this.$refs.amap) {
          this.amap = new AMap.Map(this.$refs.amap, {
            mapStyle,
            viewMode: "3D",
            terrain: true,
            resizeEnable: true,
            skyColor: "#082243",
            zoom: 11,
            ...this.ops
          })
          this.amap.on('complete', () => {
            this.amap.setFitView();//视口自适应
          })
          /*增加卫星图层*/
          if (this.satellite) {
            this.amap.add([new AMap.TileLayer.RoadNet({zIndex: 11}), new AMap.TileLayer.Satellite({zIndex: 10})])
          }
          /* end */
          this.$emit('update:map', this.amap)
          this.$emit("loaded")
          this.mapLoaded()
        }
      }).catch(() => c < 10 ? this.initMap(++c) : new Error("地图加载有问题"))
    },
    getMapArea() {
      const {mapLib: AMap} = this
      if (!!AMap) {
        new AMap.DistrictSearch({
          subdistrict: 0,   //获取边界不需要返回下级行政区
          extensions: 'all',  //返回行政区边界坐标组等具体信息
          level: 'district'  //查询行政级别为 市
        }).search(this.areaId.substring(0, 6), (status, result) => {
          const area = result?.districtList?.[0],
              bounds = area?.boundaries || [];
          let polygons = []
          if (this.onlyShowArea) {
            const mask = bounds.map(e => [e])
            polygons = bounds.map(path => new AMap.Polygon({
              path: path.map(e => [e.lng, e.lat]),
              strokeWeight: 1,
              fillOpacity: 0,
              strokeStyle: 'dashed',
              strokeColor: '#0091ea'
            }))
            this.amap.setMask(mask)
            this.is3d && this.amap.setPitch(65)
          } else {
            polygons = bounds.map(path => new AMap.Polygon({
              strokeWeight: 1,
              path: path.map(e => [e.lng, e.lat]),
              strokeStyle: 'dashed',
              fillOpacity: 0.1,
              fillColor: '#80d8ff',
              strokeColor: '#0091ea'
            }))
          }
          this.amap.add(polygons)
          this.amap.setCenter(area.center, true)
        })
      }
    },
    mapLoaded() {
      this.areaId && this.getMapArea()
      this.addPulseLines(this.areaId?.substring(0, 6))
      this.addMarkers()
    },
    addMarkers() {
      if (this.markers.length > 0 && this.mapLib && this.amap) {
        let markers = this.markers.map(e => {
          let {label, icon = "https://cdn.cunwuyun.cn/dvcp/h5/Location2.png"} = e
          return new this.mapLib.Marker({
            content: e.content || `<div class="marker">
                        <img src="${icon}"/>
                        <span>${label}</span>
                      </div>`,
            position: [e.lng, e.lat]
          })
        })
        this.amap.add(markers)
      }
    },
    addPulseLines(city) {
      let {amap: map, mapLib: lib, pulseLines} = this
      if (pulseLines && lib && map && city) {
        this.loca = new Loca.Container({map: this.amap})
        let ls = new lib.LineSearch({pageSize: 1, pageNum: 1, city}), lines = {
          type: "FeatureCollection",
          features: []
        }
        Promise.all(Array.from("0123456789").map(i => new Promise((resolve) => {
          ls.search(i, (e, res) => {
            if (e == "complete" && res.info == "OK") {
              res.lineInfo?.map(line => {
                lines.features.push({
                  type: "Feature",
                  properties: {},
                  geometry: {
                    type: "LineString",
                    coordinates: line.path?.map(p => [p.lng, p.lat]) || []
                  }
                })
              })
            }
            resolve()
          })
        }))).then(() => {
          let layer = new Loca.PulseLineLayer({
            zIndex: 10,
            opacity: 1,
            visible: true,
            zooms: [2, 22],
          })
          let geo = new Loca.GeoJSONSource({data: lines})
          layer.setSource(geo)
          layer.setStyle({
            altitude: 0,
            lineWidth: 2,
            // 脉冲头颜色
            headColor: "#B5FBFF",
            // 脉冲尾颜色
            trailColor: 'rgba(0,0,0,0)',
            // 脉冲长度，0.25 表示一段脉冲占整条路的 1/4
            interval: 0.25,
            // 脉冲线的速度，几秒钟跑完整段路
            duration: 15000,
          })
          this.loca.add(layer)
          this.loca.animate.start()
        })
      }
    }
  },
  mounted() {
    this.initMap()
  },
  destroyed() {
    this.amap?.destroy()
  }
}
</script>

<style lang="scss" scoped>
.AiMap {
  width: 100%;
  height: 100%;
  flex: 1;
  min-width: 0;
  min-height: 0;
  position: relative;

  &.mask {
    box-shadow: 0 0 40px 20px rgba(#000, .8);
  }

  .map {
    height: 100%;
  }

  .mask {
    pointer-events: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 8;
    background: radial-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .6) 40%, #000 100%);
  }

  :deep( .marker ) {
    position: relative;

    & > img {
      width: 30px;
      height: 30px;
    }

    & > span {
      display: none;
    }

    &:hover > span {
      position: absolute;
      left: 50%;
      bottom: 0;
      transform: translate(-50%, 100%);
      display: block;
      color: #fff;
      font-size: 14px;
      white-space: nowrap;
    }
  }

  :deep( .amap-logo), :deep( .amap-copyright ) {
    display: none !important;
  }

  :deep( .amap-icon ) {
    width: 40px !important;
    height: 40px !important;

    img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>
