<script setup>
import {
  Map
} from "mapbox-gl";
import { provide, onMounted } from "vue";
import { cleanMapboxInstance, useMapboxRef, onUnmounted, defineMapboxInstance, watch, useMapboxBeforeLoad, ref } from "#imports";
import { useResizeObserver } from "@vueuse/core";
const props = defineProps({
  mapId: { type: String, required: true },
  options: { type: Object, required: false },
  onError: { type: Function, required: false },
  onLoad: { type: Function, required: false },
  onIdle: { type: Function, required: false },
  onRemove: { type: Function, required: false },
  onRender: { type: Function, required: false },
  onResize: { type: Function, required: false },
  onWebglcontextlost: { type: Function, required: false },
  onWebglcontextrestored: { type: Function, required: false },
  onDataloading: { type: Function, required: false },
  onData: { type: Function, required: false },
  onTiledataloading: { type: Function, required: false },
  onSourcedataloading: { type: Function, required: false },
  onStyledataloading: { type: Function, required: false },
  onStyleImageMissing: { type: Function, required: false },
  onStyleload: { type: Function, required: false },
  onStyleimportload: { type: Function, required: false },
  onSourcedata: { type: Function, required: false },
  onStyledata: { type: Function, required: false },
  onBoxzoomcancel: { type: Function, required: false },
  onBoxzoomstart: { type: Function, required: false },
  onBoxzoomend: { type: Function, required: false },
  onTouchcancel: { type: Function, required: false },
  onTouchmove: { type: Function, required: false },
  onTouchend: { type: Function, required: false },
  onTouchstart: { type: Function, required: false },
  onClick: { type: Function, required: false },
  onContextmenu: { type: Function, required: false },
  onDblclick: { type: Function, required: false },
  onMousemove: { type: Function, required: false },
  onMouseup: { type: Function, required: false },
  onMousedown: { type: Function, required: false },
  onMouseout: { type: Function, required: false },
  onMouseover: { type: Function, required: false },
  onMovestart: { type: Function, required: false },
  onMove: { type: Function, required: false },
  onMoveend: { type: Function, required: false },
  onZoomstart: { type: Function, required: false },
  onZoom: { type: Function, required: false },
  onZoomend: { type: Function, required: false },
  onRotatestart: { type: Function, required: false },
  onRotate: { type: Function, required: false },
  onRotateend: { type: Function, required: false },
  onDragstart: { type: Function, required: false },
  onDrag: { type: Function, required: false },
  onDragend: { type: Function, required: false },
  onPitchstart: { type: Function, required: false },
  onPitch: { type: Function, required: false },
  onPitchend: { type: Function, required: false },
  onWheel: { type: Function, required: false }
});
const emit = defineEmits(["resize", "remove", "load", "render", "idle", "error", "webglcontextlost", "webglcontextrestored", "data", "styledata", "sourcedata", "dataloading", "styledataloading", "sourcedataloading", "styleimagemissing", "styleload", "styleimportload", "movestart", "move", "moveend", "drag", "dragend", "zoomstart", "zoom", "zoomend", "rotatestart", "rotate", "rotateend", "pitchstart", "pitch", "pitchend", "boxzoomstart", "boxzoomend", "boxzoomcancel", "mousedown", "mouseup", "mouseover", "mousemove", "preclick", "click", "dblclick", "mouseout", "contextmenu", "wheel", "touchstart", "touchend", "touchmove", "touchcancel"]);
provide("MapID", props.mapId);
watch(() => {
  return Object.entries(props).filter((arr) => arr[0].toString().startsWith("on"));
}, (value) => {
  for (const [key, v] of value) {
    if (v) {
      const passMap = ["resize", "remove", "load", "render", "idle", "error", "webglcontextlost", "webglcontextrestored"];
      const eventName = key.toString().replace("on", "").toLowerCase();
      let mbEventName = eventName;
      if (eventName === "styleload") mbEventName = "style.load";
      if (eventName === "styleimportload") mbEventName = "style.import.load";
      useMapboxBeforeLoad(props.mapId, (map) => {
        map.on(mbEventName, (e) => {
          emit(eventName, passMap.includes(eventName) ? map : e);
        });
      });
    }
  }
}, { immediate: true });
watch(() => props.options, (newOptions, oldOptions) => {
  const map = useMapboxRef(props.mapId);
  if (newOptions) {
    if (newOptions.style && oldOptions?.style !== newOptions.style) {
      map.value?.setStyle(newOptions.style);
    }
    if (newOptions.center && oldOptions?.center !== newOptions.center) {
      map.value?.setCenter(newOptions.center);
    }
    if (newOptions.zoom && oldOptions?.zoom !== newOptions.zoom) {
      map.value?.setZoom(newOptions.zoom);
    }
    if (newOptions.projection && oldOptions?.projection !== newOptions.projection) {
      map.value?.setProjection(newOptions.projection);
    }
    if (newOptions.bearing && oldOptions?.bearing !== newOptions.bearing) {
      map.value?.setBearing(newOptions.bearing);
    }
    if (newOptions.pitch && oldOptions?.pitch !== newOptions.pitch) {
      map.value?.setPitch(newOptions.pitch);
    }
    if (newOptions.minZoom && oldOptions?.minZoom !== newOptions.minZoom) {
      map.value?.setMinZoom(newOptions.minZoom);
    }
    if (newOptions.maxZoom && oldOptions?.maxZoom !== newOptions.maxZoom) {
      map.value?.setMaxZoom(newOptions.maxZoom);
    }
    if (newOptions.bounds && oldOptions?.bounds !== newOptions.bounds) {
      map.value?.fitBounds(newOptions.bounds);
    }
  }
});
const mapContainerRef = ref();
onMounted(() => {
  let map = useMapboxRef(props.mapId);
  if (!map.value) {
    map = defineMapboxInstance(props.mapId, {
      ...props.options,
      container: mapContainerRef.value || props.mapId
    });
  }
  useResizeObserver(mapContainerRef, () => {
    setTimeout(() => map.value?.resize(), 0);
  });
});
onUnmounted(() => {
  cleanMapboxInstance(props.mapId);
});
</script>

<template>
  <div
    :id="mapId"
    ref="mapContainerRef"
    class="mapboxgl-default-map-size"
    :class="$attrs.class"
    :style="$attrs.style"
  />
  <slot />
</template>

<style>
.mapboxgl-default-map-size{bottom:0;position:absolute;top:0;width:100%}
</style>
