<script setup>
import { MapMouseEvent } from "mapbox-gl";
import { inject } from "vue";
import { computed, onUnmounted, watch, useMapboxInstance, useMapbox, useMapboxBeforeLoad, useAttrs, useMapboxRef, onMounted, _useMapboxInstanceWithLoaded } from "#imports";
import { whenever } from "@vueuse/core";
const props = defineProps({
  layer: { type: Object, required: true },
  beforeLayer: { type: String, required: false },
  onMousedown: { type: Function, required: false },
  onMouseup: { type: Function, required: false },
  onMouseover: { type: Function, required: false },
  onMousemove: { type: Function, required: false },
  onClick: { type: Function, required: false },
  onDblclick: { type: Function, required: false },
  onMouseenter: { type: Function, required: false },
  onMouseleave: { type: Function, required: false }
});
const emit = defineEmits(["mousedown", "mouseup", "mouseover", "mousemove", "click", "dblclick", "mouseenter", "mouseleave"]);
const mapId = inject("MapID");
if (!mapId) throw "Mapbox Controls must be placed inside a Map component";
const attrs = useAttrs();
if (attrs.source || attrs.sourceId) throw "source & sourceId props in MapboxLayer are deprecated";
watch(() => {
  return Object.entries(props).filter((arr) => arr[0].toString().startsWith("on"));
}, (value) => {
  for (const [key, v] of value) {
    if (v) {
      const eventName = key.toString().replace("on", "").toLowerCase();
      useMapboxBeforeLoad(mapId, (map) => {
        map.on(eventName, props.layer.id, (e) => {
          emit(eventName, e);
        });
      });
    }
  }
}, { immediate: true });
const mapRef = useMapboxRef(mapId);
const sourceExists = computed(() => {
  return !!mapRef.value?.getSource(
    props.layer.source?.toString() || ""
  );
});
const layerExists = computed(() => {
  return !!mapRef.value?.getLayer(props.layer.id);
});
useMapbox(mapId, (map) => {
  function addLayer() {
    if (!sourceExists.value) {
      return;
    }
    if (map.getLayer(props.layer.id)) {
      console.warn(`Mapbox layer with id '${props.layer.id}' was initialized multiple times. This can cause unexpected behaviour.`);
      return;
    }
    if (props.beforeLayer && map.getLayer(props.beforeLayer)) {
      map?.addLayer(props.layer, props.beforeLayer);
    } else {
      if (props.beforeLayer) {
        watch(() => map.getLayer(props.beforeLayer || ""), () => {
          map?.moveLayer(props.layer.id, props.beforeLayer);
        });
      }
      map?.addLayer(props.layer);
    }
  }
  addLayer();
  whenever(sourceExists, addLayer);
  watch(layerExists, () => {
    if (!layerExists.value && sourceExists.value) {
      addLayer();
    }
  });
});
watch(() => props.layer, (newLayer, oldLayer) => {
  if (!mapId) return;
  const map = useMapboxRef(mapId);
  if (newLayer) {
    if (newLayer.minzoom) {
      map.value?.setLayerZoomRange(newLayer.id, newLayer.minzoom || 0, newLayer.maxzoom || 0);
    }
    if (newLayer.maxzoom) {
      map.value?.setLayerZoomRange(newLayer.id, newLayer.minzoom || 0, newLayer.maxzoom || 0);
    }
    if (newLayer.paint) {
      for (const prop of Object.keys(newLayer.paint || {})) {
        map.value?.setPaintProperty(newLayer.id, prop, newLayer.paint?.[prop]);
      }
    }
    if (newLayer.layout) {
      for (const prop of Object.keys(newLayer.layout || {})) {
        map.value?.setLayoutProperty(newLayer.id, prop, newLayer.layout?.[prop]);
      }
    }
    if (newLayer.filter) {
      map.value?.setFilter(newLayer.id, newLayer.filter);
    }
  }
}, { deep: true });
onUnmounted(() => {
  useMapbox(mapId, (map) => {
    if (map.getLayer(props.layer.id)) {
      map?.removeLayer(props.layer.id);
    }
  });
});
</script>

<template>
  <div>
    <slot />
  </div>
</template>
