<script>
import { getCurrentInstance, h, inject, onBeforeUnmount, provide, shallowRef, useSlots, render as vueRender, watch } from "vue";
import { MARKER_CLUSTERER_INJECTION_KEY } from "./types";
import { bindGoogleMapsEvents, MAP_INJECTION_KEY, useGoogleMapsResource } from "./useGoogleMapsResource";
export { MARKER_CLUSTERER_INJECTION_KEY };
</script>

<script setup>
const props = defineProps({
  options: { type: Object, required: false }
});
const emit = defineEmits(["click", "clusteringbegin", "clusteringend"]);
defineSlots();
const markerClustererEvents = [
  "click",
  "clusteringbegin",
  "clusteringend"
];
const slots = useSlots();
const instance = getCurrentInstance();
const mapContext = inject(MAP_INJECTION_KEY, void 0);
const clusteringVersion = shallowRef(0);
const renderedContainers = [];
function cleanupRenderedClusters() {
  for (const container of renderedContainers) {
    vueRender(null, container);
  }
  renderedContainers.length = 0;
}
onBeforeUnmount(cleanupRenderedClusters);
const markerClusterer = useGoogleMapsResource({
  async create({ map, mapsApi }) {
    const { MarkerClusterer } = await import("@googlemaps/markerclusterer");
    if (slots.renderer) {
      await mapsApi.importLibrary("marker");
    }
    const clusterer = new MarkerClusterer({
      map,
      ...props.options,
      ...slots.renderer ? {
        renderer: {
          render(cluster, stats) {
            const container = document.createElement("div");
            const vnode = h({
              render: () => slots.renderer?.({ cluster, stats, map })
            });
            if (instance) {
              vnode.appContext = instance.appContext;
            }
            vueRender(vnode, container);
            renderedContainers.push(container);
            const marker = new mapsApi.marker.AdvancedMarkerElement({
              position: cluster.position,
              content: container.firstElementChild || container
            });
            return marker;
          }
        }
      } : {}
    });
    bindGoogleMapsEvents(clusterer, emit, { withPayload: markerClustererEvents });
    clusterer.addListener("clusteringbegin", () => {
      cleanupRenderedClusters();
    });
    clusterer.addListener("clusteringend", () => {
      clusteringVersion.value++;
    });
    return clusterer;
  },
  cleanup(clusterer, { mapsApi }) {
    mapsApi.event.clearInstanceListeners(clusterer);
    clusterer.setMap(null);
    cleanupRenderedClusters();
  }
});
const rerenderPending = shallowRef(false);
function requestRerender() {
  rerenderPending.value = true;
}
watch(
  () => rerenderPending.value && markerClusterer.value,
  (ready) => {
    if (!ready)
      return;
    if (!mapContext?.map.value?.getProjection())
      return;
    rerenderPending.value = false;
    try {
      markerClusterer.value.render();
    } catch (err) {
      if (import.meta.dev) {
        console.error("[nuxt-scripts] MarkerClusterer render failed:", err);
      }
    }
  }
);
provide(
  MARKER_CLUSTERER_INJECTION_KEY,
  {
    markerClusterer,
    requestRerender,
    clusteringVersion
  }
);
</script>

<template>
  <slot v-if="markerClusterer" />
</template>
