<template>
  <audio ref="audio" :src="audioSrc" loop preload="auto" />
</template>

<script lang="ts">
import { defineComponent, PropType, ref, watch } from "vue";
import { BoundingBox } from "@/components/SVGContent.vue";
import { queueAudioForLoading } from "@/services/AssetLoader";

export default defineComponent({
  name: "AudioArea",
  props: {
    definition: {
      type: Object as PropType<AudioAreaDef>,
      required: true,
    },
    bbox: {
      type: Object as PropType<BoundingBox>,
      required: true,
    },
  },
  setup(props) {
    const audio = ref<HTMLAudioElement | null>(null);
    const audioSrc = ref<string>(""); // Ref to hold audio source after preloading
    const isPreloaded = ref<boolean>(false);
    const distance = ref<number>(0);

    console.debug(`[AUDIOAREA] Initializing ${props.definition.src}...`);
    console.debug(props.definition);

    // Preload the audio file completely to avoid keeping connections open
    // Use the global audio loading queue to throttle concurrent loads
    const preloadAudio = (src: string) => {
      console.debug(`[AUDIOAREA] Queueing audio for preload: ${src}`);
      audioSrc.value = "empty.mp3";

      queueAudioForLoading(
        src,
        () => distance.value,
        (blobUrl) => {
          // Use blob URL to avoid keeping connections open
          audioSrc.value = blobUrl;
          isPreloaded.value = true;
          console.debug(`[AUDIOAREA] Successfully preloaded audio: ${src}`);
        },
        (error) => {
          console.error(`[AUDIOAREA] Error preloading audio: ${error}`);
          // Fall back to original source if preloading fails
          audioSrc.value = src;
        }
      );
    };

    // Start preloading when component is created
    preloadAudio(props.definition.src);

    const MIN_SCALE = 0.02;
    const MIN_VOLUME_MULTIPLIER = 0.33;
    const vol_x = (1 - MIN_VOLUME_MULTIPLIER) / (1 - MIN_SCALE);
    const vol_b = 1 - vol_x;

    const onBBoxChange = () => {
      if (!audioSrc.value) return;

      const x = props.bbox.x + props.bbox.w / 2;
      const y = props.bbox.y + props.bbox.h / 2;
      distance.value = Math.hypot(
        x - props.definition.cx,
        y - props.definition.cy
      );

      if (distance.value < props.definition.radius) {
        if (audio.value!.paused) {
          console.debug(
            `[AUDIOAREA] Entered audio area "${props.definition.src}", starting playback...`
          );
          audio.value!.play();
        }
        const volume =
          (props.definition.radius - distance.value) / props.definition.radius;
        audio.value!.volume =
          volume * (props.bbox.z < 1 ? props.bbox.z * vol_x + vol_b : 1);
      } else {
        if (!audio.value!.paused) {
          console.debug(
            `[AUDIOAREA] Left audio area "${props.definition.src}", pausing playback...`
          );
          audio.value!.pause();
        }
      }
    };
    watch(props.bbox, onBBoxChange, { deep: true });

    return {
      audio,
      audioSrc,
    };
  },
});

export interface AudioAreaDef {
  id: string;
  cx: number;
  cy: number;
  radius: number;
  src: string;
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>
