<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import useCrs from '../hook/useCrs.ts'
import useZoom from '../hook/useZoom.ts'
import { useResizeObserver } from '@vueuse/core'

const mapContainer = ref()
const map = ref<L.Map>()
const layers = ref<L.TileLayer[]>([])
const slotProps = ref({
  contextmenu: {}
})

const baiduCrs = useCrs('baiduCrs')
const gaodeCrs = useCrs('gaodeCrs')

const mapFilter = ref('invert(1) grayscale(.2) saturate(0.8) brightness(1.8) opacity(1) hue-rotate(184deg) sepia(17%)'); // 地图滤镜


const mapInfo: Record<string, { crs: L.Proj.CRS | L.CRS, url: string, error: string, center: L.LatLngExpression }> = {
  baidu: {
    crs: baiduCrs,
    url: "http://172.20.10.2/baidumaps/roadmap/{z}/{x}/{y}.png",
    error: 'http://172.20.10.2/baidumaps/roadmap/error.png',
    center: [39.926474, 116.403283]
  },
  gaode: {
    crs: gaodeCrs,
    url: "http://172.20.10.2/mapabc/roadmap/{z}/{x}/{y}.png",
    error: 'http://172.20.10.2/baidumaps/roadmap/error.png',
    center: [-97.00238024827533, 210.7725501856634]
  },
  gaodeLine: {
    crs: gaodeCrs,
    url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
    error: 'http://172.20.10.2/baidumaps/roadmap/error.png',
    center: [-97.00238024827533, 210.7725501856634]
  }

}


provide('map', map) // 注入的内容 mapChild 下

onMounted(() => {
  // const selfZoom = useZoom(mapContainer,map, [3,6,9,14,16,18])

  // L.Map.addInitHook('addHandler','scrollWheelZoom', selfZoom)
  // L.Map.mergeOptions({
  //   scrollWheelZoom:true
  // })

  const use: keyof typeof mapInfo = 'gaode'

  map.value = L.map(mapContainer.value, {
    center: mapInfo[use].center,
    zoom: 13,
    attributionControl: false,
    crs: mapInfo[use].crs,
    zoomControl: false,
  });

  // const scale= L.control.scale({ maxWidth: 200, metric: true, imperial: true });
  // map.value.addControl(scale)
  const layer = L.tileLayer(mapInfo[use].url, {
    minZoom: 3,
    maxZoom: 18,
    tms: true,
    errorTileUrl: mapInfo[use].error,
    className: "mapFilter",
  })

  // map.value.on('zoom', (e) => {
  //   console.log(e.target._animateToZoom)
  // })

  layers.value?.push(layer)

  layer.addTo(map.value)

  map.value.addEventListener("contextmenu", (e) => {
    slotProps.value.contextmenu = e
  })

})

function flyTo(latLng: [number, number]) {
  map.value?.flyTo(L.latLng(latLng[0], latLng[1]))
}

function changeZoom(zoomSize: [number, number]) {
  map.value?.setMinZoom(zoomSize[0])
  map.value?.setMaxZoom(zoomSize[1])
}

function changeMapFilter(filterInfo: Record<'blur' |
  'brightness' |
  'contrast' |
  'drop-shadow' |
  'grayscale' |
  'hue-rotate' |
  'invert' |
  'opacity' |
  'saturate' |
  'sepia', string | number>) {
  mapFilter.value = Object.entries(filterInfo).map(([key, value]) => `${key}(${value})`).join(' ')
}

function changeMapUrl(urlTemplate: string, errorTileUrl: string) {
  if (!layers.value[0]) return;
  layers.value[0].setUrl(urlTemplate);
  layers.value[0].options.errorTileUrl = errorTileUrl;
}

function changeAnimation(zoomAnimation: boolean, fadeAnimation: boolean) {
  if (!map.value) return;
  map.value.options.zoomAnimation = zoomAnimation
  map.value.options.fadeAnimation = fadeAnimation
}


function changeZoomSnap(zoomAnimation: number) {
  if (!map.value) return;
  map.value.options.zoomSnap = zoomAnimation
}


function pushLayers(addlayers: L.TileLayer[]) {
  const _map = map.value
  if (!_map) return
  addlayers.forEach(l => {
    if (_map.hasLayer(l)) return;
    layers.value.push(l)
    l.addTo(_map)
  })
}

useResizeObserver(mapContainer, () => map.value?.invalidateSize(true))

defineExpose({ flyTo, changeZoom, changeMapFilter, changeMapUrl, pushLayers, changeAnimation,changeZoomSnap })
</script>

<template>
  <div class="mapContainer" ref="mapContainer" :style="{ '--mapFilter': mapFilter }">
    <slot v-if="map" v-bind="slotProps"></slot>
  </div>
</template>

<style  lang="scss">
.mapContainer {
  grid-area: map;
}

body.body--dark {
  .mapFilter {
    filter: var(--mapFilter);
  }
}
</style>
