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

	const mapContainer = ref();
	const { map, tileLayers, props: mapProps } = useMap(mapContainer, { use: 'gaode', zoom: 13 });

	// const config = defineModel<Object>()

	const slotProps = ref({
		contextmenu: {},
	});

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

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

	onMounted(() => {
		map.value?.addEventListener('contextmenu', (e) => {
			slotProps.value.contextmenu = e;
		});
	});

	watch({ center: mapProps.value.center }, ({ center }) => center && map.value?.flyTo(center));
	watch({ max: mapProps.value.maxZoom || 0 }, ({ max }) => map.value?.setMaxZoom(max));
	watch({ min: mapProps.value.minZoom || 0 }, ({ min }) => map.value?.setMaxZoom(min));
	watch({ url: mapProps.value.urlTemplate }, ({ url }) => url && tileLayers.value[0].setUrl(url));
	watch({ zoomSnap: mapProps.value.zoomSnap }, ({ zoomSnap }) => map.value && (map.value.options.zoomSnap = zoomSnap));

	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(' ');
	}

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

	defineExpose({ changeMapFilter, setOptions });
</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>
