<script>
import { defu } from "defu";
import { useHead, useRuntimeConfig } from "nuxt/app";
import { withQuery } from "ufo";
import { computed, onMounted, ref } from "vue";
import { scriptRuntimeConfig } from "#nuxt-scripts/utils";
import { useScriptProxyUrl } from "../../composables/useScriptProxyUrl";
</script>

<script setup>
const props = defineProps({
  center: { type: [String, Object], required: false },
  zoom: { type: Number, required: false, default: 15 },
  size: { type: null, required: false },
  scale: { type: Number, required: false, default: 2 },
  format: { type: String, required: false },
  maptype: { type: String, required: false },
  mapId: { type: String, required: false },
  markers: { type: [String, Array], required: false },
  path: { type: [String, Array], required: false },
  visible: { type: [String, Array], required: false },
  style: { type: [String, Array], required: false },
  language: { type: String, required: false },
  region: { type: String, required: false },
  signature: { type: String, required: false },
  apiKey: { type: String, required: false },
  width: { type: [Number, String], required: false, default: 640 },
  height: { type: [Number, String], required: false, default: 400 },
  loading: { type: String, required: false, default: "lazy" },
  objectFit: { type: String, required: false, default: "cover" },
  imgAttrs: { type: Object, required: false }
});
defineSlots();
const runtimeConfig = useRuntimeConfig();
const proxyConfig = runtimeConfig.public["nuxt-scripts"]?.googleStaticMapsProxy;
const apiKey = props.apiKey || scriptRuntimeConfig("googleMaps")?.apiKey;
const useProxy = !props.apiKey && proxyConfig?.enabled;
const proxyUrl = useScriptProxyUrl();
if (import.meta.dev) {
  if (!apiKey && !useProxy)
    console.warn("[nuxt-scripts] ScriptGoogleMapsStaticMap requires a Google Maps API key with Static Maps API access. Set NUXT_PUBLIC_SCRIPTS_GOOGLE_MAPS_API_KEY in your .env, or enable the proxy via `scripts.registry.googleMaps`.");
}
const rootEl = ref();
const measuredSize = ref();
function clampStaticMapSize(width, height, max = 640) {
  const ratio = Math.min(1, max / Math.max(width, height));
  return `${Math.max(1, Math.floor(width * ratio))}x${Math.max(1, Math.floor(height * ratio))}`;
}
onMounted(() => {
  if (props.size || !rootEl.value)
    return;
  const { offsetWidth, offsetHeight } = rootEl.value;
  if (offsetWidth > 0 && offsetHeight > 0) {
    measuredSize.value = clampStaticMapSize(offsetWidth, offsetHeight);
  }
});
function toCssUnit(value) {
  return typeof value === "number" ? `${value}px` : value;
}
const PIXEL_VALUE_RE = /^\d+(?:px)?$/i;
function isPixelValue(value) {
  if (typeof value === "number")
    return true;
  return PIXEL_VALUE_RE.test(value);
}
function transformMapStyles(styles) {
  return styles.map((s) => {
    const feature = s.featureType ? `feature:${s.featureType}` : "";
    const element = s.elementType ? `element:${s.elementType}` : "";
    const rules = (s.stylers || []).map((styler) => {
      return Object.entries(styler).map(([key, value]) => {
        if (key === "color" && typeof value === "string")
          value = value.replace("#", "0x");
        return `${key}:${value}`;
      }).join("|");
    }).filter(Boolean).join("|");
    return [feature, element, rules].filter(Boolean).join("|");
  }).filter(Boolean);
}
function resolveStyle(style) {
  if (!style)
    return void 0;
  if (typeof style === "string")
    return style;
  if (Array.isArray(style) && style.length > 0 && typeof style[0] === "string")
    return style;
  return transformMapStyles(style);
}
function resolveCenter(center) {
  if (!center)
    return void 0;
  if (typeof center === "string")
    return center;
  return `${center.lat},${center.lng}`;
}
const resolvedSize = computed(() => {
  if (props.size)
    return props.size;
  if (measuredSize.value)
    return measuredSize.value;
  if (isPixelValue(props.width) && isPixelValue(props.height))
    return clampStaticMapSize(Number.parseInt(String(props.width)), Number.parseInt(String(props.height)));
  return "640x400";
});
const src = computed(() => {
  const query = {
    center: resolveCenter(props.center),
    zoom: props.zoom,
    size: resolvedSize.value,
    scale: props.scale,
    format: props.format,
    maptype: props.maptype,
    map_id: props.mapId,
    markers: props.markers,
    path: props.path,
    visible: props.visible,
    style: resolveStyle(props.style),
    language: props.language,
    region: props.region,
    signature: props.signature,
    key: useProxy ? void 0 : apiKey
  };
  for (const key of Object.keys(query)) {
    if (query[key] === void 0)
      delete query[key];
  }
  if (useProxy) {
    return proxyUrl("/_scripts/proxy/google-static-maps", query);
  }
  return withQuery("https://maps.googleapis.com/maps/api/staticmap", query);
});
const imgAttributes = computed(() => {
  return defu(props.imgAttrs, {
    src: src.value,
    alt: "Google Maps",
    loading: props.loading,
    style: {
      width: "100%",
      height: "100%",
      objectFit: props.objectFit,
      display: "block"
    }
  });
});
const rootStyle = computed(() => ({
  width: toCssUnit(props.width),
  height: toCssUnit(props.height),
  maxWidth: "100%",
  overflow: "hidden"
}));
if (import.meta.server) {
  useHead({
    link: [
      {
        rel: props.loading === "eager" ? "preconnect" : "dns-prefetch",
        href: useProxy ? void 0 : "https://maps.googleapis.com"
      }
    ].filter((l) => l.href)
  });
}
defineExpose({ src });
</script>

<template>
  <div ref="rootEl" :style="rootStyle">
    <slot :src="src">
      <img v-bind="imgAttributes">
    </slot>
  </div>
</template>
