<template>
  <div id="MapContainer" :style="`width:${width}`" />
</template>

<script lang="ts">
import { computed, defineComponent, nextTick, onMounted, PropType } from 'vue'
import store from '@/store'
declare const SMap: any
declare const Plugins: any

interface PointProp {
  data: unknown[]
  key: string
  labelKey?: string
  icon?: string
  size?: number | number[]
  color?: string
}

export default defineComponent({
  name: 'MyMap',
  displayName: 'm-map',
  props: {
    config: {
      type: Object as PropType<{ [key: string]: unknown }>,
      default: null,
    },
    width: {
      type: String as PropType<string>,
      default: '67vw',
    },
  },
  emits: ['complete', 'event'],
  setup(props, ctx) {
    const curMapType = computed(() => store.state.curMapType)
    let map: any = null
    // onMounted(async () => {
    //   await nextTick()
    //   initMap()
    // })
    function initMap(config?: any) {
      map = new SMap.Map('MapContainer', {
        viewMode: '3D',
        center: [1019.614669, 54.167243],
        // center: [-135.98002789627407, -722.1597065437004],
        zooms: [8, 12],
        zoom: 8,
        pitch: 45,
        mapStyle: 'smap://styles/dark',
        showBuildingBlock: true,
        ...config,
        ...props.config,
      }).on(SMap.MapEvent.maploaded, () => {
        setMouseEvent(false)
        // setBuildingBlock()
        ctx.emit('complete', map)
        addListener()
        hideCommunity()
      })
    }
    function setMouseEvent(val: boolean) {
      map.enableMouseEvent(val)
    }
    function layer(name: string) {
      return map.getLayer(name)
    }
    function setBuildingBlock(val = false) {
      map.getLayer('model_white_zw').visible = val // 整个街道图层名
      map.getLayer('model_white_zhenxing2').visible = val // 振兴小区名
      map.getLayer('model_white_WEIHAI33').visible = val // 威海小区名
      map.getLayer('model_white_dyjd').visible = val // 第一街道名
    }
    function hideCommunity() {
      map.hideXQ_Poly()
      map.hideMPZ()
      map.hideXQ_Point()
    }
    function showCommunity() {
      map.showXQ_Poly()
      map.showMPZ()
      map.showXQ_Point()
    }
    function setFilter(arr: unknown[], key = 'sect_id') {
      if (arr.length === 0) return
      const valid = arr.map((val) => {
        return `${key} = '${val}'`
      })
      map.setFilter('wg_gis_xq_point', valid.join(' or '))
      map.setFilter('wg_gis_mpz', valid.join(' or '))
      map.setFilter('wg_gis_xq_poly', valid.join(' or '))
    }
    function addListener() {
      // 触发地图点击事件
      map.on(SMap.MapEvent.click, (view: any, eventParamter: any) => {
        const { x, y } = eventParamter.mapPoint
        console.log([x, y])
        // console.log(map.getZoom(), map.getCenter())
        view.hitTest(eventParamter).then((res: any) => {
          if (res.results && res.results.length > 0) {
            ctx.emit(
              'event',
              res.results[0] && res.results[0].graphic.attributes
            )
          }
        })
      })
    }
    /**
     * ------  聚焦点位 -------
     * @param {String} x [必填 - x坐标]
     * @param {String} y [必填 - y坐标]
     * @param {Number} zoom [可选 - 放大比例（默认为6）]
     */
    function focus(x: string | number, y: string | number, zoom = 6) {
      if (!map || !x || !y) {
        console.error('传入的坐标点不能为空')
        return
      }
      curMapType.value === '3D'
        ? map.setZoomAndCenter(zoom, [+x, +y, 0])
        : map.setZoomAndCenter(zoom, [+x, +y])
    }

    function zoom(type: string) {
      if (type === 'in') map.zoomIn()
      else map.zoomOut()
    }

    // 添加边界
    function addBoundary({
      name = '',
      weight = 10,
      count = 10,
      color = 'rgba(51,145,255,.6)',
      maskColor = [0, 17, 33, 0.9],
    }) {
      const boundary = {
        boundaryType: 'jd_boundary',
        boundaryDefinition: `name like '%${name}%'`,
        boundarydistance: weight,
        bounarycount: count,
        boundaryColor: color,
        maskColor: maskColor,
      }
      const Boundary = new Plugins.MaskBoundary(map.view)
      Boundary.add(boundary)
      return Boundary
    }

    function rotate(deg: number) {
      map.setRotation(deg)
    }
    function cameraTo({
      center = [0, 0],
      heading = 180,
      tilt = 45,
    }: {
      center: number[]
      heading: number
      tilt: number
    }) {
      // map.setPitch(60)
      // map.setCenter(0, 0, 0)
      // map.setRotation(180)

      map.view.goTo({
        // center,
        heading,
        tilt,
      })
    }
    // 将数据转换为符合地图的点数组
    function getMapPoints({
      data = [],
      key,
      labelKey,
      icon,
      size,
      color = '#47B3FF',
    }: PointProp) {
      return data.map((item: any) => {
        let sizeProp = Array.isArray(size)
          ? new SMap.Size(size[0], size[1])
          : new SMap.Size(size, size)
        if (item.size) {
          sizeProp = Array.isArray(item.size)
            ? new SMap.Size(item.size[0], item.size[1])
            : new SMap.Size(item.size, item.size)
        }
        const result = {
          icon: new SMap.Icon({
            size: sizeProp,
            image: item.icon || icon,
          }),
          attributes: { key, ...item },
          position: [
            item.communityMinx || item.X || item.x || item.gpsx,
            item.communityMiny || item.Y || item.y || item.gpsy,
            item.communityMinz || item.Z || item.z || item.gpsz || 0,
          ],
          label: new SMap.Label({
            text: labelKey ? (item[labelKey] || item[key]) + '' : '',
            size,
            color,
          }),
        }
        return new SMap.Marker(result)
      })
    }
    // 添加点
    function addPoint({
      key,
      data = [],
      labelKey = '',
      icon = 'test.png',
      size = 14,
      color = '#47B3FF',
    }: PointProp) {
      if (!map) return
      const points = getMapPoints({ data, key, labelKey, icon, size, color })
      console.log(points)
      map.add(points)
      return points
    }

    // 删除点
    function remove(points: any) {
      if (!map || !points) return
      map.remove(points)
    }

    // 添加线状覆盖物
    function addPolyLine({
      paths,
      attributes = {},
      strokeColor = 'rgba(51,145,255,.6)',
      width = 2,
    }: {
      paths: any[]
      attributes: any
      strokeColor: string
      width: number
    }) {
      const polyline = new SMap.Polyline({
        path: paths.map((item: any) => new SMap.LngLat(item[0], item[1])),
        attributes,
        cap: 'square',
        strokeColor,
        style: 'solid',
        lineJoin: 'round',
        width,
      })
      map.add(polyline)
      return polyline
    }

    return {
      initMap,
      focus,
      zoom,
      setMouseEvent,
      layer,
      setBuildingBlock,
      hideCommunity,
      showCommunity,
      addBoundary,
      rotate,
      cameraTo,
      addPoint,
      addPolyLine,
      remove,
      setFilter,
    }
  },
})
</script>

<style lang="stylus" scoped>
#MapContainer
  position fixed
  height 100vh
  top 0
  left 0
</style>
<style lang="stylus">
.esri-component.esri-attribution.esri-widget
  display none
</style>
