<script lang="ts" setup>
import {
  defineExpose,
  defineProps,
  reactive,
  ref,
  watchEffect,
} from 'vue'
import AmapApi, {
  type Poi,
  type SearchPlaceResult,
} from '@/components/a-map/amap-api.ts'
import {
  ElOption,
  ElPagination,
  ElSelect,
} from 'element-plus'
import Strings from '@/common/utils/strings.ts'

const key = '3TGBZ-ZK7K5-CMNIK-ICIGZ-K6TYQ-HTBTZ'

interface AMapPropsType {
  width?: string
  height?: string
  mapConfig: {
    lat: number
    lng: number
    /**
     * 缩放级别
     */
    zoom?: number
    /**
     * 俯仰角
     */
    pitch?: number
    /**
     * 旋转角度
     */
    rotation?: number
  }
}

const props = withDefaults(
  defineProps<AMapPropsType>(),
  {
    width: '500px',
    height: '100%',
  },
)

const addressModel = defineModel<string>('address', {required: false})
const latModel = defineModel<number>('lat', {required: false})
const lngModel = defineModel<number>('lng', {required: false})
const areaModel = defineModel<number | string>('area', {required: false})
const areaNameModel = defineModel<string>('areaName', {required: false})

const mapWrapper = useTemplateRef<HTMLDivElement>('mapRef')
let map: TMap.Map | null = null
let multiMarker: TMap.MultiMarker | null = null
const paginationData = reactive<{
  current: number
  size: number
  total: number
}>({
  current: 1,
  size: 10,
  total: 0,
})
const pois = ref<Poi[]>([])
let keywords: string | undefined = undefined
const currentPoi = ref<string>('')

function onSelected(value: string) {
  const poi = pois.value.find((it) => it.id === value)
  if (!poi) return
  addressModel.value = poi.title + '(' + poi.address + ')'
  latModel.value = poi.location.lat
  lngModel.value = poi.location.lng
  areaModel.value = poi.ad_info.adcode
  areaNameModel.value = poi.ad_info.city
}

function createMap() {
  if (mapWrapper.value == null) {
    console.error('地图容器不存在')
    return null
  }
  if (map != null) return map
  return new TMap.Map(mapWrapper.value, {
    center: new TMap.LatLng(props.mapConfig.lat, props.mapConfig.lng),
    zoom: props.mapConfig.zoom ?? 16,
    pitch: props.mapConfig.pitch ?? 0,
    rotation: props.mapConfig.rotation ?? 0,
  })
}

function createMarkerLayer() {
  if (map == null) return null
  if (multiMarker != null) return multiMarker
  return new TMap.MultiMarker({
    map,
    geometries: [
      {
        id: '1',
        position: new TMap.LatLng(props.mapConfig.lat, props.mapConfig.lng),
      },
    ],
  })
}

watchEffect(() => {
  if (Strings.isBlank(currentPoi.value)) return
  const poi = pois.value.find((it) => it.id === currentPoi.value)
  if (!poi) return
  map?.setCenter(new TMap.LatLng(poi.location.lat, poi.location.lng))
  multiMarker?.updateGeometries([
    {
      id: '1',
      position: new TMap.LatLng(poi.location.lat, poi.location.lng),
    },
  ])
})

function paginationChange() {
  doSearch()
}

function doSearch(queryStr?: string) {
  if (!Strings.isBlank(queryStr)) keywords = queryStr
  if (Strings.isBlank(keywords)) return
  AmapApi.searchPlace({
    key,
    keyword: keywords!,
    boundary: {lat: props.mapConfig.lat, lng: props.mapConfig.lng},
    page_size: paginationData.size,
    page_index: paginationData.current,
    get_subpois: 1,
  }).then((res) => {
    if (!res) return
    const result = res as SearchPlaceResult
    paginationData.total = result.count
    pois.value = result.data
  })
}

function init() {
  if (mapWrapper.value == null) return
  try {
    map = createMap()
    multiMarker = createMarkerLayer()
  } catch (e) {
    console.log(e)
  }
}

function destroy() {
  multiMarker?.destroy()
  map?.destroy()
  multiMarker = null
  map = null
}

onMounted(() => {
  nextTick(init)
})


onBeforeUnmount(destroy)

defineExpose({init, destroy})
</script>

<template>
  <div class="a-map">
    <ElSelect
      v-model="currentPoi"
      :placeholder="addressModel??'请搜索地点'"
      :remote-method="doSearch"
      filterable
      no-data-text="暂无数据"
      no-match-text="暂无数据"
      remote
      @change="onSelected">
      <ElOption
        v-for="item in pois"
        :key="item.id"
        :label="item.title+'('+item.address+')'"
        :value="item.id"
      />
      <template #footer>
        <ElPagination
          :background="true"
          :current-page="paginationData.current"
          :hide-on-single-page="false"
          :page-size="paginationData.size"
          :teleported="false"
          :total="paginationData.total"
          layout="total, prev, pager, next,"
          @change="paginationChange"
          @update:current-page="(val) => paginationData.current = val"
          @update:page-size="(val) => paginationData.size = val"
        />
      </template>
    </ElSelect>
    <div ref="mapRef" class="map-wrapper"></div>
  </div>
</template>

<style lang="stylus" scoped>
.a-map {
  width v-bind('props.width');
  height v-bind('props.height');
  display flex;
  flex-direction column;
  gap 10px

  :deep(.el-select) {
    height 32px
    width 100%;
  }
}

.map-wrapper {
  flex 1
  width 100%;
}

:deep(.el-pagination) {
  justify-content center
}
</style>
