<template>
  <el-dialog
    title="选择位置"
    :visible.sync="open"
    :close-on-click-modal="false"
    width="700px"
    append-to-body
    @close="cancel"
  >
    <!-- 输入框 -->
    <el-autocomplete
      class="mb10"
      style="width: 100%"
      v-model="address"
      value-key="name"
      popper-class="my-autocomplete"
      placeholder="请输入内容"
      :fetch-suggestions="querySearchAsync"
      clearable
      @select="handleSelect"
    >
      <i class="el-icon-search el-input__icon" slot="suffix"></i>
      <template slot-scope="{ item }">
        <div class="name">{{ item.name }}</div>
        <span class="addr">{{ item.district }}</span>
      </template>
    </el-autocomplete>
    <!-- 地图容器 -->
    <div ref="container" class="container"></div>
    <div class="footer" slot="footer">
      <el-button type="primary" @click="submitForm">确 定</el-button>
    </div>
  </el-dialog>
</template>

<script>
let map = null,
  marker = null
export default {
  name: 'BaseAmapSelect',
  data() {
    return {
      open: false,
      latitude: null,
      longitude: null,
      address: null,
      defaultCenter: [116.41, 39.9]
    }
  },
  destroyed() {
    console.log('销毁')
    map && (map = undefined)
  },
  methods: {
    // 重置数据
    reset() {
      this.latitude = null
      this.longitude = null
      this.address = null
    },
    // 打开组件
    init(options) {
      this.reset()
      this.open = true
      // 初始化地图
      // 无需频繁初始化地图
      if (!map) {
        this.$nextTick(() => {
          this.creatAmap(options)
        })
      } else {
        // 移动视角
        if (options.cityId) {
          // 如果设置了cityId就移动至cityId
          this.getLocationByCityId(options.cityId).then(res => {
            map.setCenter(res)
          })
        } else if (options.center) {
          // 如果设置了经纬度就移动至经纬度地址
          map.setCenter(options.center)
        }
      }
    },
    // 加载地图
    async creatAmap(options) {
      let pOptions = options || {}
      // 初始化参数
      let creatOptions = {
        resizeEnable: true, //窗口大小调整
        center: this.defaultCenter,
        zoom: 15,
        ...pOptions
      }
      try {
        // 如果设置了cityId，将center改为cityId解析后的点位
        if (pOptions.cityId) {
          // console.log(pOptions.cityId);
          creatOptions.center = await this.getLocationByCityId(pOptions.cityId)
        }
      } catch (error) {
        console.log('初始化地图出错：', error)
      } finally {
        map = new AMap.Map(this.$refs.container, creatOptions)
        this.mapAddClick()
      }
    },
    // 给地图添加点击事件
    mapAddClick() {
      if (AMap && map) {
        let geoCoder = new AMap.Geocoder()
        map.on('click', e => {
          if (marker) {
            map.remove(marker)
          }
          // 添加标记点
          marker = new AMap.Marker({
            position: e.lnglat,
            map: map
          })

          geoCoder.getAddress(e.lnglat, (status, res) => {
            if (status === 'complete' && res.info === 'OK') {
              this.address = res.regeocode.formattedAddress
              this.latitude = e.lnglat.lat
              this.longitude = e.lnglat.lng
            } else {
              this.$message({
                message: '获取位置信息失败！',
                type: 'warning'
              })
            }
          })
        })
      }
    },
    // 根据cityId搜索坐标
    getLocationByCityId(cityId) {
      if (AMap && cityId) {
        return new Promise((resolve, reject) => {
          // 基础配置
          const districtSearchOptions = {
            showbiz: false,
            subdistrict: 0
          }
          const amapDistrictSearch = new AMap.DistrictSearch(districtSearchOptions)
          amapDistrictSearch.search(cityId, (status, result) => {
            if (status === 'complete' && result.info === 'OK') {
              // 取数组第一个
              if (result.districtList[0]) {
                const resCenter = result.districtList[0].center
                resolve([resCenter.lng, resCenter.lat])
              }
            } else {
              reject(status)
            }
            // console.log('s:', status);
            // console.log('r:', result);
          })
        })
      } else {
        return Promise.reject('no AMap or no Id')
      }
    },
    // 搜索输入
    querySearchAsync(queryString, cb) {
      // 插件配置
      const autoOptions = {}
      let aMapAutoComplete = null
      if (AMap && queryString) {
        aMapAutoComplete = new AMap.AutoComplete(autoOptions)
        // 搜索
        aMapAutoComplete.search(queryString, (status, result) => {
          if (status === 'complete' && result.info === 'OK') {
            cb(result.tips)
          }
          // console.log('s:', status);
          // console.log('r:', result);
        })
      }
    },
    // 选择搜索项
    handleSelect(item) {
      // console.log(item);
      if (map) {
        map.setCenter([item.location.lng, item.location.lat])
        if (marker) {
          map.remove(marker)
        }
        // 添加标记点
        marker = new AMap.Marker({
          position: [item.location.lng, item.location.lat],
          map: map
        })
        // 给表单数据
        this.address = item.district + item.address
        this.latitude = item.location.lat
        this.longitude = item.location.lng
      }
    },
    // 确认按钮
    submitForm() {
      if (this.address && this.latitude && this.longitude) {
        const data = {
          address: this.address,
          latitude: this.latitude,
          longitude: this.longitude
        }
        this.$emit('get-address', data)
        this.open = false
      } else {
        this.msgError('请选择地点！')
      }
    },
    // 取消按钮
    cancel() {
      // 关闭地图清空按钮
      if (map && marker) {
        map.remove(marker)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  width: 100%;
  height: 600px;
}

.footer {
  padding: 0 20px 10px;
}

// 自定义样式
.my-autocomplete {
  li {
    line-height: normal;
    padding: 7px;

    .name {
      text-overflow: ellipsis;
      overflow: hidden;
    }

    .addr {
      font-size: 12px;
      color: #b4b4b4;
    }

    .highlighted .addr {
      color: #ddd;
    }
  }
}
</style>
