<template>
  <div class="search-layout">
    <el-input v-model="keyword" placeholder="输入名称搜索" style="width: 350px" clearable>
      <template #append>
        <el-button :icon="Search" />
      </template>
    </el-input>
    <div class="search-result" v-show="keyword" ref="resultEl"></div>
  </div>
  <div class="def-select-map" ref="mapEl"></div>
  <div class="def-map-info" v-if="info">
    <p><span>经度</span>{{ info.lat }}</p>
    <p><span>维度</span>{{ info.lng }}</p>
    <p><span>缩放级别</span>{{ info.zoom }}</p>
  </div>
</template>

<script setup lang="ts">
import AMapLoader from "@amap/amap-jsapi-loader";
import { Search } from "@element-plus/icons-vue";
import { ref, watchEffect } from "vue";
import { QuiskExpose } from "@/helper/mount";
import { debounce } from "@/util";

export type MapImage = { blob: Blob | null };
type MapInfo = { lat: number; lng: number; zoom: number };

const keyword = ref("");
const info = ref<MapInfo>();

const mapEl = ref<HTMLDivElement>();
const resultEl = ref<HTMLDivElement>();
const searchAMap = ref<any>();

watchEffect(async (onCleanup) => {
  if (!mapEl.value || !resultEl.value) {
    return;
  }
  const AMap = await AMapLoader.load({
    plugins: ["AMap.PlaceSearch"],
    key: "e661b00bdf2c44cccf71ef6070ef41b8",
    version: "2.0",
  });

  const map = new AMap.Map(mapEl.value, {
    WebGLParams: {
      preserveDrawingBuffer: true,
    },
    resizeEnable: true,
  });
  const placeSearch = new AMap.PlaceSearch({
    pageSize: 5,
    pageIndex: 1,
    map: map,
    panel: resultEl.value,
    autoFitView: true,
  });
  const getMapInfo = (): MapInfo => {
    var zoom = map.getZoom(); //获取当前地图级别
    var center = map.getCenter();
    return {
      zoom,
      lat: center.lat,
      lng: center.lng,
    };
  };
  //绑定地图移动与缩放事件
  map.on("moveend", () => (info.value = getMapInfo()));
  map.on("zoomend", () => (info.value = getMapInfo()));
  searchAMap.value = placeSearch;

  onCleanup(() => {
    searchAMap.value = null;
    map.destroy();
  });
});

const search = debounce((keyword: string) => {
  searchAMap.value.search(keyword);
}, 1000);
watchEffect(() => {
  searchAMap.value && search(keyword.value);
});

defineExpose<QuiskExpose>({
  submit() {
    return new Promise<MapImage>((resolve) => {
      if (mapEl.value) {
        const canvas = mapEl.value.querySelector("canvas") as HTMLCanvasElement;
        canvas.toBlob((blob) => resolve({ blob }));
      } else {
        resolve({ blob: null });
      }
    });
  },
});
</script>

<style lang="scss" scoped>
.search-layout {
  display: inline-block;
  position: relative;
  margin-bottom: 15px;
  z-index: 2;
}

.search-result {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 1;
  overflow: hidden;

  &.show {
    max-height: 450px;
    overflow-y: auto;
  }
}

.def-map-info {
  margin-top: 10px;
  p {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.85);
    display: inline;
    &:not(:last-child)::after {
      content: ",";
      margin-right: 6px;
    }
  }

  span::after {
    content: "：";
  }
}

.def-select-map {
  width: 540px;
  height: 390px;
  z-index: 1;
}
</style>
