<template>
  <el-form-item
    v-if="activated"
    v-show="visible"
    :label="field.label"
    :prop="field.name"
    :class="{ 'form-item': true, readonly: readonly }"
    :style="{ marginBottom: colMarginY }"
  >
    <template v-slot:label>
      <Tooltip :field="field" />
    </template>
    <el-button :style="{ width: fullWidth ? '100%' : '' }" @click="show">
      <i class="el-icon-map-location" />
      {{ btnLabel }}
    </el-button>
    <el-dialog
      v-model="dialogVisible"
      :visible.sync="dialogVisible"
      width="600px"
      :append-to-body="true"
      @opened="onShow"
      @close="popoverVisible = false"
    >
      <div style="position: relative;">
        <div ref="mapRoot" style="width: 100%; height: 240px;" />
        <el-popover
          v-model="searchPopoverVisible"
          placement="bottom-start"
          width="340"
          trigger="manual"
          :visible.sync="searchPopoverVisible"
        >
          <template #reference>
            <el-input
              ref="searchInput"
              v-model="search"
              size="mini"
              prefix-icon="el-icon-search"
              clearable
              style="position: absolute; top: 10px; left: 10px; width: 200px;"
              @focus="popoverVisible = false"
            />
          </template>
          <div style="height: 120px; overflow-y: overlay;">
            <div
              v-for="location in searchLocations"
              :key="location.uid"
              class="location-item"
              @click="pickLocation(location)"
            >
              <div class="title">
                {{ location.title }}
              </div>
              <div class="address">
                {{ location.shortAddress }}
              </div>
            </div>
          </div>
        </el-popover>
        <el-popover
          v-model="popoverVisible"
          v-model:visible="popoverVisible"
          placement="top"
          title="附近地点"
          width="340"
          trigger="manual"
        >
          <template #reference>
            <div
              style="
                position: absolute;
                left: 50%; margin-left: -10px;
                top: 100px;
                height: 20px; width: 20px; line-height: 20px;
                font-size: 20px;
                color: #006EBBFF;"
            >
              <i class="el-icon-location" />
            </div>
          </template>
          <div style="height: 120px; overflow-y: overlay;">
            <div
              v-for="location in popoverLocations"
              :key="location.uid"
              class="location-item"
              @click="pickLocation(location)"
            >
              <div class="title">
                {{ location.title }}
              </div>
              <div class="address">
                {{ location.shortAddress }}
              </div>
            </div>
          </div>
        </el-popover>
      </div>
      <el-form label-position="right" label-width="40px" class="china-location-form">
        <el-row :gutter="15">
          <el-col v-if="mapLng" :span="12">
            <el-form-item label="经度" style="margin-bottom: 0;">
              <el-input v-model="lng" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col v-if="mapLat" :span="12">
            <el-form-item label="纬度" style="margin-bottom: 0;">
              <el-input v-model="lat" />
            </el-form-item>
          </el-col>
          <el-col v-if="mapProvince" :span="8">
            <el-form-item label="省" style="margin-bottom: 0;">
              <el-input v-model="province" />
            </el-form-item>
          </el-col>
          <el-col v-if="mapCity" :span="8">
            <el-form-item label="市" style="margin-bottom: 0;">
              <el-input v-model="city" />
            </el-form-item>
          </el-col>
          <el-col v-if="mapDistrict" :span="8">
            <el-form-item label="区" style="margin-bottom: 0;">
              <el-input v-model="district" />
            </el-form-item>
          </el-col>
          <el-col v-if="mapAddress" :span="24">
            <el-form-item label="地址" style="margin-bottom: 0;">
              <el-input v-model="address" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- <el-image :src="imgSrc" style="width: 100px; height: 62px; margin-top: 15px;" /> -->
      </el-form>
      <template v-slot:footer>
        <div style="height: 40px;">
          <el-button type="primary" style="float: right; margin-left: 15px;" @click="onPick">
            确定
          </el-button>
          <el-button style="float: right;" @click="dialogVisible = false">
            取消
          </el-button>
        </div>
      </template>
    </el-dialog>
  </el-form-item>
</template>

<style scoped>
/* 滚动条样式 */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
  border-radius: 4px;
  background-color: #f9f9f9;
}
::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background-color: #efefef;
}
.china-location-form .el-form-item {
  margin-top: 15px;
}
.location-item {
  height: 50px;
  padding: 8px 0;
  margin-right: 20px;
  border-bottom: 1px solid #eee;
  cursor: pointer;
}
.location-item:last-of-type {
  border-bottom: none;
}
.location-item:hover {
  background-color: #ecf5ff;
}
.location-item .title {
  height: 18px;
  line-height: 18px;
  color: #777;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
.location-item .address {
  margin-top: 4px;
  height: 12px;
  line-height: 12px;
  font-size: 12px;
  color: #aaa;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
</style>

<script>
import formItemMixin from "../../common/form-item/mixin";

export default {
  mixins: [formItemMixin],
  data() {
    return {
      valueText: "",
      dialogVisible: false,
      scriptLoaded: false,
      mounted: false,
      showed: false,
      map: null,
      popoverVisible: false,
      popoverLocations: [],
      search: "",
      searchLocations: [],
      searchPopoverVisible: false,
      lng: "",
      lat: "",
      province: "",
      city: "",
      district: "",
      address: ""
      // imgSrc: ''
    };
  },
  computed: {
    ready() {
      return this.scriptLoaded && this.mounted && this.showed;
    },
    btnLabel() {
      return this.field.btnLabel || "地图选点";
    },
    fullWidth() {
      return !!this.field.fullWidth;
    },
    mapLng() {
      return !!this.field.mapLng;
    },
    lngKey() {
      return this.field.lngKey || "longitude";
    },
    mapLat() {
      return !!this.field.mapLat;
    },
    latKey() {
      return this.field.latKey || "latitude";
    },
    mapProvince() {
      return !!this.field.mapProvince;
    },
    provinceKey() {
      return this.field.provinceKey || "province";
    },
    mapCity() {
      return !!this.field.mapCity;
    },
    cityKey() {
      return this.field.cityKey || "city";
    },
    mapDistrict() {
      return !!this.field.mapDistrict;
    },
    districtKey() {
      return this.field.districtKey || "district";
    },
    mapAddress() {
      return !!this.field.mapAddress;
    },
    addressKey() {
      return this.field.addressKey || "address";
    }
  },
  watch: {
    ready() {
      const map = new BMap.Map(this.$refs.mapRoot, {
        enableMapClick: false
      });
      this.map = map;
      map.setDefaultCursor("pointer");
      // map.centerAndZoom(new BMap.Point(this.lng, this.lat), 15);
      this.lng = this.mapLng ? this.data[this.lngKey] || 120.19 : 120.19;
      this.lat = this.mapLat ? this.data[this.latKey] || 30.26 : 30.26;
      this.centerToPoint(new BMap.Point(this.lng, this.lat), true);

      map.enableScrollWheelZoom();
      map.addEventListener("click", e => {
        this.popoverVisible = false;
        const { point } = e;
        this.pickPoint(point);
      });
    },
    search(val) {
      if (val) {
        const localSearch = new BMap.LocalSearch(this.map, {
          pageCapacity: 6
        });
        localSearch.setSearchCompleteCallback(res => {
          const suggestions = [];
          const { province, city } = res;
          const num = res.getCurrentNumPois();
          for (let i = 0; i < num; i++) {
            const point = res.getPoi(i);
            suggestions.push(this.makeShortAddress(point, province, city));
          }

          this.searchLocations = suggestions;
          this.searchPopoverVisible = true;
        });
        localSearch.search(val);
      }
    }
  },
  created() {
    const ak = this.config.baiduAk;
    if (!ak) {
      // eslint-disable-next-line
      return console.error("未找到百度地图 appkey，请在 config.baiduAk 中设置");
    }
    const src = `//api.map.baidu.com/api?v=2.0&ak=${ak}&callback=BMapInit`;
    if (!document.querySelector('script[src="' + src + '"]')) {
      const script = document.createElement("script");
      script.src = src;
      window.BMapInit = () => {
        this.scriptLoaded = true;
      };
      document.head.appendChild(script);
    } else {
      this.scriptLoaded = true;
    }
  },
  mounted() {
    this.mounted = true;
  },
  methods: {
    show() {
      this.dialogVisible = true;
    },
    onShow() {
      this.showed = true;

      this.lng = this.mapLng ? this.data[this.lngKey] || 120.19 : 120.19;
      this.lat = this.mapLat ? this.data[this.latKey] || 30.26 : 30.26;
      if (this.map) {
        this.centerToPoint(new BMap.Point(this.lng, this.lat));
      }

      this.province = this.mapProvince ? this.data[this.provinceKey] : "";
      this.city = this.mapCity ? this.data[this.cityKey] : "";
      this.district = this.mapDistrict ? this.data[this.districtKey] : "";
      this.address = this.mapAddress ? this.data[this.addressKey] : "";
    },
    onPick() {
      if (this.mapLng) {
        this.$set(this.data, this.lngKey, this.lng);
      }
      if (this.mapLat) {
        this.$set(this.data, this.latKey, this.lat);
      }
      if (this.mapProvince) {
        this.$set(this.data, this.provinceKey, this.province);
      }
      if (this.mapCity) {
        this.$set(this.data, this.cityKey, this.city);
      }
      if (this.mapDistrict) {
        this.$set(this.data, this.districtKey, this.district);
      }
      if (this.mapAddress) {
        this.$set(this.data, this.addressKey, this.address);
      }

      this.dialogVisible = false;
    },
    pickPoint(point) {
      this.$refs.searchInput.blur();
      this.lng = point.lng;
      this.lat = point.lat;
      // const ak = '*******';
      // this.imgSrc = `http://api.map.baidu.com/panorama/v2?ak=${ak}&width=100&height=62&location=${this.lng},${this.lat}&fov=180`
      const geocoder = new BMap.Geocoder();
      geocoder.getLocation(point, res => {
        this.address = res.address;
        const { province, city, district } = res.addressComponents;
        this.province = this.getSpecialRegion(province);
        // 考虑直辖市情况
        this.city = this.getCity(province, city, district);
        this.district = district;
        this.popoverLocations = res.surroundingPois.map(point => {
          return this.makeShortAddress(point, province, city);
        });

        this.centerToPoint(point);
        this.popoverVisible = true;
      });
    },
    centerToPoint(point, init) {
      const map = this.map;
      if (!init) {
        map.panTo(point);
      } else {
        map.centerAndZoom(point, 15);
      }
    },
    makeShortAddress(point, province, city) {
      const { address } = point;
      let shortAddress = address;
      if (shortAddress && shortAddress.startsWith(province)) {
        shortAddress = shortAddress.replace(province, "");
      }
      if (shortAddress && shortAddress.startsWith(city)) {
        shortAddress = shortAddress.replace(city, "");
      }
      point.shortAddress = shortAddress;
      return point;
    },
    pickLocation(location) {
      const { point, shortAddress, title } = location;
      this.lng = point.lng;
      this.lat = point.lat;
      const geocoder = new BMap.Geocoder();
      geocoder.getLocation(point, res => {
        const { province, city, district } = res.addressComponents;
        const resProvince = this.getSpecialRegion(province);
        this.province = resProvince;
        let addr = shortAddress.endsWith(title) ? shortAddress : `${shortAddress}${title}`;
        // 解决 addr 与省市一致的情况
        if (addr === resProvince || addr === city) {
          addr = district;
        }
        this.city = city;
        if (province === city) {
          // 考虑直辖市情况
          this.city = this.getCity(province, city, district);
          this.address = `${resProvince}${addr}`;
          this.valueText = `${resProvince}\n${addr}`;
        } else {
          this.address = `${resProvince}${city}${addr}`;
          this.valueText = `${resProvince}${city}\n${addr}`;
        }
        this.district = district;
      });

      this.centerToPoint(point);
      this.popoverVisible = false;
      this.searchPopoverVisible = false;
      this.$refs.searchInput.blur();
      this.search = "";
    },
    getCity(province, city, district) {
      if (province !== city) {
        return city;
      }
      // 处理重庆特殊情况
      if (city === "重庆市" && district) {
        let suffix = "市辖区";
        if (district.endsWith("县")) {
          suffix = "县";
        }
        return `${city}-${suffix}`;
      }
      return this.getSpecialRegion(city);
    },
    // 处理特区名称
    getSpecialRegion(name) {
      if (name === "香港" || name === "澳门") {
        return `${name}特别行政区`;
      }
      return name;
    }
  }
};
</script>
