<!--
  封装高德地图选址组件
  initMapData: { areacode:[],  areacodeNames:[], address: '', lnglat: '' } //areacode 位置、 省市县名称字符串数组、 详细地址， 经纬度（中间,分割） 
  @author terrfly
  @site https://www.jeequan.com
  @date 2022/05/07 11:34
-->
<template>
  <a-row>
    <a-col :span="isMobile ? 24 : 12">
      <a-form-item label="选址省/市/区" name="areacode">
        <JeepayAreaSelect
          ref="jeepayAreaSelect"
          v-model:value="vdata.mapData.areacode"
          @change="changeAreaCodeFunc"
          :getPopupContainer="(triggerNode) => (triggerNode.parentElement)"
        />
      </a-form-item>
    </a-col>
    <a-col :span="isMobile ? 24 : 12">
      <a-form-item label="具体位置" name="address">
        <a-input
          id="amap-search-input"
          v-model:value="vdata.mapData.address"
          autoComplete="off"
        />
      </a-form-item>
    </a-col>
    <a-col :span="isMobile ? 24 : 12">
      <a-form-item label="经纬度" name="lnglat">
        <a-input v-model:value="vdata.mapData.lnglat" autoComplete="off" />
      </a-form-item>
    </a-col>
  </a-row>
  
  <a-collapse v-model:activeKey="vdata.showKey" @change="changeMap">
    <a-collapse-panel key="map" header="地图选址">
      <div :id="vdata.mapDivId" :style="{width: '100%', height: isMobile?'300px':'600px'}">MAP</div>
    </a-collapse-panel>
  </a-collapse>
</template>
  <script lang="ts" setup>
  import { $getMapConfig } from '@/api/manage'
  import { reactive, ref, inject } from 'vue'
  import AMapLoader from '@amap/amap-jsapi-loader'
  
  // emit 父组件使用： v-model="val" 进行双向绑定。
  const emit = defineEmits(['update:value', 'change'])
  
  // 参数注入： 是否手机端
  let isMobile : any = inject('isMobile')
  
  const vdata: any = reactive({
    showKey: 'map',
    mapData: { areacode: [], areacodeNames: [], address: '', lnglat: '' }, //areacode 位置、 省市县、
  
    mapDivId: 'mapDIV_' + new Date().getTime()
  
  })
  
  const jeepayAreaSelect = ref()
  
  // 地图对象
  let AMapInstantiate = null as any // 地图实例
  let AMapDefine = null as any // 地图定义，初始成功返回的定义对象， 可以通过 AMapDefine.map等获取
  let AMapDistrictSearch = null as any // 区域搜索插件
  let AMapMarker = null as any //标记点
  let AutoComplete = null as any //自动录入组件
  
  /** 初始化  */
  function init(initMapData) {
    // 清空数据
    vdata.mapData.areacode = initMapData.areacode || []
    // vdata.mapData.areacodeNames = initMapData.areacodeNames || []
    vdata.mapData.lnglat = initMapData.lnglat
    vdata.mapData.address = initMapData.address
  
    AMapInstantiate = null as any // 地图实例
    AMapDefine = null as any // 地图定义，初始成功返回的定义对象， 可以通过 AMapDefine.map等获取
    AMapDistrictSearch = null as any // 区域搜索插件
    AMapMarker = null as any //标记点
    AutoComplete = null as any //自动录入组件
  
    // 获取地图配置参数
    $getMapConfig()
      .then((res) => {
        // @ts-ignore window._AMapSecurityConfig
        window._AMapSecurityConfig = { securityJsCode: res.apiMapWebSecret }
        return AMapLoader.load({
          // 申请好的Web端开发者Key，首次调用 load 时必填
          key: res.apiMapWebKey,
  
          // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
          version: '2.0',
  
          // 同步加载插件
          plugins: [
            'AMap.ToolBar',
            'AMap.Scale',
            'AMap.Marker',
            'AMap.PlaceSearch',
            'AMap.AutoComplete',
            'AMap.Geocoder',
            'AMap.DistrictSearch',
          ],
        })
      })
      .then((AMap) => {
        // 定义
        AMapDefine = AMap
  
        // 实例化
        AMapInstantiate = new AMapDefine.Map(vdata.mapDivId, {
          viewMode: '3D',
        })
  
        AMapInstantiate.addControl(new AMapDefine.ToolBar()) // 工具栏
        AMapInstantiate.addControl(new AMapDefine.Scale()) // 比例尺
  
        // geocoder 地理位置查询插件
        var geocoder = new AMap.Geocoder()
  
        AMapDistrictSearch = new AMapDefine.DistrictSearch()
  
        // 输入提示插件
        AutoComplete = new AMapDefine.AutoComplete({
          input: 'amap-search-input',
          citylimit: true,
        })
  
        // 搜索到内容后的回调函数
        AutoComplete.on('select', function (e) {
          let name = e.poi.name // 搜索到的名称
          selectLocationFunc(e.poi.location.lng, e.poi.location.lat, name)
        })
  
        // 地图的选中后的回调函数
        AMapInstantiate.on('click', (e) => {
          // 查询省市县、 位置信息
          geocoder.getAddress(
            new AMapDefine.LngLat(e.lnglat.getLng(), e.lnglat.getLat()),
            function (state, result) {
              // 查找失败
              if (state != 'complete') {
                return false
              }
  
              // 限制城市搜索
              AutoComplete.setCity(result.regeocode.addressComponent.citycode)
  
              // 更改省市县  --> 组件调用change事件
              jeepayAreaSelect.value.changeByAreacode(
                result.regeocode.addressComponent.adcode
              )
  
              // 选中的点
              selectLocationFunc(
                e.lnglat.getLng(),
                e.lnglat.getLat(),
                result.regeocode.formattedAddress
              )
            }
          )
        })
  
        // 存在数据
        if (initMapData.lnglat) {
          AMapInstantiate.setCenter(
            new AMapDefine.LngLat(
              initMapData.lnglat.split(',')[0],
              initMapData.lnglat.split(',')[1]
            )
          )
          selectLocationFunc(
            initMapData.lnglat.split(',')[0],
            initMapData.lnglat.split(',')[1],
            initMapData.address
          )
  
           // 查询省市县、 位置信息 ( 限制城市搜索 )
           geocoder.getAddress(new AMapDefine.LngLat(initMapData.lnglat.split(',')[0], initMapData.lnglat.split(',')[1]), function (state, result) {
              // 查找失败
              if (state != 'complete') {
                return false
              }
              // 限制城市搜索
              AutoComplete.setCity(result.regeocode.addressComponent.citycode)
            })
  
        }
      })
  }
  
  // 选中某个点的事件： 定位到当前地点
  function selectLocationFunc(lng, lat, name = null) {
    if (name) {
      vdata.mapData.address = name
    }
  
    if (!lng || !lat) {
      return false
    }
  
    // 更改经纬度坐标
    changeInputLnglat(lng, lat)
  
    if (AMapMarker == null) {
      // 创建地图标点中心点
      AMapMarker = new AMapDefine.Marker({
        position: new AMapDefine.LngLat(lng, lat), // 经纬度对象，也可以是经纬度构成的一维数组[116.39, 39.9]
      })
      AMapInstantiate.add([AMapMarker])
    } else {
      AMapMarker.setPosition(new AMapDefine.LngLat(lng, lat))
    }
  }
  
  // 选择省市县的回调函数
  function changeAreaCodeFunc(areacode, val) {
    // 无无变化
    if (vdata.mapData.areacode && vdata.mapData.areacode[2] == val[2]) {
      return
    }
  
    // 设置地图的city
    AMapInstantiate.setCity(val[2])
  
    // 限制城市搜索
    AutoComplete.setCity(val[2])
  
    //
    vdata.mapData.areacode = val
    vdata.mapData.areacodeNames = [
      areacode[0].label,
      areacode[1].label,
      areacode[2].label,
    ]
  }
  
  // 更改输入框的 经纬度
  function changeInputLnglat(lng, lat) {
    vdata.mapData.lnglat = lng + ',' + lat
  }
  
  function getMapData() {
    return vdata.mapData
  }
    //   在移动端收起展开后地图组件未能加载 所以要重新初始化
  const changeMap=(key)=>{    
      if(isMobile && key[0] == 'map'){
          init(vdata.mapData)
      }
  }
  defineExpose({ init, getMapData })
  </script>
  