<template>
  <div class="map-container">
    <div class="map-form">
      <xl-form :inline="true">
        <xl-form-item>
          <xl-button type="primary" icon="el-icon-location" @click="upMap"
            >地图选择</xl-button
          >
        </xl-form-item>
        <xl-form-item label="经度">
          <span>{{ lng }}</span>
        </xl-form-item>
        <xl-form-item label="纬度">
          <span>{{ lat }}</span>
        </xl-form-item>
        <xl-form-item label="当前选择的地址">
          <span>{{ positionLocal }}</span>
        </xl-form-item>
      </xl-form>
    </div>
    <xl-dialog
      title="地图"
      :visible.sync="showMap"
      @opened="initMap"
      :close-on-click-modal="false"
      width="50%"
    >
      <xl-form>
        <xl-row>
          <xl-col :span="4">
            <xl-form-item>
              <xl-select v-model="map.origin1" @change="origin1Change">
                <xl-option
                  v-for="item in dict.originList"
                  :key="item.id"
                  :value="item.id"
                  :label="item.fullname"
                />
              </xl-select>
            </xl-form-item>
          </xl-col>
          <xl-col :span="4">
            <xl-form-item>
              <xl-select v-model="map.origin2" @change="getChildren2">
                <xl-option
                  v-for="item in cities"
                  :key="item.id"
                  :value="item.id"
                  :label="item.fullname"
                />
              </xl-select>
            </xl-form-item>
          </xl-col>
          <xl-col :span="4">
            <xl-form-item>
              <xl-select v-model="map.origin3">
                <xl-option
                  v-for="item in dict.origin3List"
                  :key="item.id"
                  :value="item.id"
                  :label="item.fullname"
                />
              </xl-select>
            </xl-form-item>
          </xl-col>
          <xl-col :span="8">
            <xl-form-item>
              <xl-autocomplete
                placeholder="请输入具体地址"
                v-model="map.keyword"
                :debounce="800"
                value-key="title"
                :fetch-suggestions="searchPoi"
                value="location"
                @select="selectPosi"
              ></xl-autocomplete>
            </xl-form-item>
          </xl-col>
        </xl-row>
      </xl-form>
      <div class="cont">
        <span>经度：{{ lng }}</span>
        <span>纬度：{{ lat }}</span>
        <span>当前地址：{{ positionLocal }}</span>
      </div>
      <div class="container-inner-map"></div>
      <span slot="footer" class="dialog-footer">
        <xl-button @click="cancelSelect">取 消</xl-button>
        <xl-button type="primary" @click="savePosi">确 定</xl-button>
      </span>
    </xl-dialog>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      default: ''
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      lat: '31.937739751899553', // 纬度
      lng: '118.82612949739269', // 经度
      positionLocal: '暂无地址',
      adcode: '',
      positionId: '',
      showMap: false,
      map: {
        origin1: '',
        origin2: '',
        origin3: '',
        keyword: ''
      },
      mapCom: null,
      dict: {
        originList: [],
        origin2List: [],
        origin3List: []
      }
    }
  },
  computed: {
    cities() {
      if (this.map.origin1) {
        const startString = this.map.origin1.substring(0, 2)
        return this.dict.origin2List.filter(item => item.id.startsWith(startString))
      } else {
        return []
      }
    },
    url() {
      const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${this.lat},${this.lng}&key=AZ4BZ-GST62-OC5UL-C7HDU-B5A4H-QCBH6&output=jsonp`
      return url
    },
    latLng() {
      return `${this.lat},${this.lng},${this.positionLocal},${this.adcode}`
    }
  },
  methods: {
    selectPosi({ location: { lat, lng },title }) {
      this.lat = lat
      this.lng = lng
      this.searchLocation()
      const center = new window.qq.maps.LatLng(lat, lng)
      this.mapCom.setCenter(center)
      let anchor = new qq.maps.Point(6, 6),
        size = new qq.maps.Size(24, 24),
        origin = new qq.maps.Point(0, 0),
        icon = new qq.maps.MarkerImage('https://mapapi.qq.com/web/lbs/javascriptV2/demo/img/center.gif', size, origin, anchor);
      new window.qq.maps.Marker({
        icon,
        map: this.mapCom,
        position: center
      })
    },
    async searchPoi(val, cb) {
      if (val) {
        const { location } = this.dict.origin3List.find(item => item.id === this.map.origin3)
        const url = `https://apis.map.qq.com/ws/place/v1/search?output=jsonp&key=AZ4BZ-GST62-OC5UL-C7HDU-B5A4H-QCBH6&keyword=${val}&boundary=nearby(${location.lat},${location.lng},1000,1)&callback=`
        const res = await this.getJsonData(url)
        cb(res.data)
      } else {
        cb([])
      }
    },
    getJsonData(url) {
      const cb = 'cbFunction'
      return new Promise((resolve, reject) => {
        try {
          window[cb] = function (res) {
            window[cb] = null
            document.body.removeChild(mapsct)
            resolve(res)
          }
          const mapsct = document.createElement('script')
          mapsct.src = url + cb
          document.body.appendChild(mapsct)
        } catch (e) {
          reject(e)
        }
      })
    },
    async districtList() {
      const url = "https://apis.map.qq.com/ws/district/v1/list?key=AZ4BZ-GST62-OC5UL-C7HDU-B5A4H-QCBH6&output=jsonp&callback="
      const { result } = await this.getJsonData(url)
      this.dict.originList = result[0]
      this.dict.origin2List = result[1]
    },
    async getChildren2(val) {
      this.map.origin3 = ''
      if (!val) {
        _this.dict.origin3List = []
      }
      const url = `https://apis.map.qq.com/ws/district/v1/getchildren?id=${val}&key=AZ4BZ-GST62-OC5UL-C7HDU-B5A4H-QCBH6&output=jsonp&callback=`
      const { result } = await this.getJsonData(url)
      this.dict.origin3List = result[0]
    },
    upMap() {
      this.showMap = true
    },
    savePosi() {
      this.$emit('input', this.latLng)
      this.showMap = false
    },
    initMap() {
      if(this.positionId){
        this.initForm(this.positionId)
      }
      const map = new window.qq.maps.Map(
        this.$el.querySelector('.container-inner-map'),
        {
          center: new window.qq.maps.LatLng(this.lat, this.lng),
          zoom: 13
        }
      )
      // 实例化自动完成
      const ap = new window.qq.maps.place.Autocomplete(
        this.$el.querySelector('.container-inner-place')
      )
      let keyword = ''
      // 调用Poi检索类。用于进行本地检索、周边检索等服务。
      const searchService = new window.qq.maps.SearchService({
        complete: function (results) {
          if (results.type === 'CITY_LIST') {
            searchService.setLocation(results.detail.cities[0].cityName)
            searchService.search(keyword)
            return
          }
          const pois = results.detail.pois
          const latlngBounds = new window.qq.maps.LatLngBounds()
          for (let i = 0, l = pois.length; i < l; i++) {
            const poi = pois[i]
            latlngBounds.extend(poi.latLng)
            const marker = new window.qq.maps.Marker({
              map: map,
              position: poi.latLng
            })
            marker.setTitle(poi.name)
          }
          map.fitBounds(latlngBounds)
        }
      })
      // 添加监听事件
      window.qq.maps.event.addListener(ap, 'confirm', (res) => {
        keyword = res.value
        searchService.search(keyword)
      })
      let marker = new qq.maps.Marker({
        position: new window.qq.maps.LatLng(this.lat, this.lng),
        map: map
      });
      window.qq.maps.event.addListener(map, 'click', (evt) => {
        this.lat = evt.latLng.lat
        this.lng = evt.latLng.lng
        this.searchLocation()
	      marker.setPosition(evt.latLng);
        })
      this.mapCom = map
    },
    jsonp(url, callback) {
      var callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random())
      window[callbackName] = function (data) {
        delete window[callbackName]
        document.body.removeChild(script)
        callback(data)
      }

      var script = document.createElement('script')
      script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName
      document.body.appendChild(script)
    },
    searchLocation() {
      this.jsonp(this.url, (data) => {
        this.positionLocal = data.result?.address
        this.adcode = data.result?.ad_info.adcode
      })
    },
    cancelSelect() {
      const val = this.value
      const tempArr = val.split(',')
      this.lat = tempArr[0] || '31.937739751899553'
      this.lng = tempArr[1] || '118.82612949739269'
      this.positionLocal = tempArr[2] || '暂无地址'
      this.showMap = false
    },
    origin1Change() {
      this.map.origin2 = ''
      this.map.origin3 = ''
      this.dict.origin3List = []
    },
    async initForm(val) {
      const orignId1 = val.slice(0,2) + '0000'
      const orignId2 = val.slice(0,4) + '00'
      const orignId3 = val
      this.map.origin1 = orignId1
      this.map.origin2 = orignId2
      await this.getChildren2(this.map.origin2)
      this.map.origin3 = orignId3
    }
  },
  watch: {
    value: {
      handler(val) {
        //   纬度,精度
        if (val) {
          const tempArr = val.split(',')
          this.lat = tempArr[0] || '31.937739751899553'
          this.lng = tempArr[1] || '118.82612949739269'
          this.positionLocal = tempArr[2] || '暂无地址'
          this.positionId = tempArr[3] || ''
        }
      },
      immediate: true
    },
    adcode: {
      handler(val) {
        if (val) {
          this.initForm(val)
        }
      },
      immediate: true
    }
  },
  mounted() {
    this.districtList()
  }
}
</script>

<style scoped>
.container-inner-map {
  height: 400px;
}
.input-map {
  width: 250px;
}
.map-search {
  display: flex;
  align-items: center;
}
.mg-r-15 {
  margin-right: 15px;
}
.cont {
  margin-bottom: 20px;
}
.cont span {
  margin-right: 20px;
}
.map-form {
  margin-bottom: 15px;
}
</style>
