<script setup lang="ts">
import { ref, watch } from "vue";
import MediaLoadingState from "@/components/creative/MediaLoadingState.vue";

defineOptions({ inheritAttrs: false });

const props = withDefaults(
  defineProps<{
    type: "image" | "video";
    src: string;
    compact?: boolean;
    loadingLabel?: string;
    errorLabel?: string;
  }>(),
  { compact: false, loadingLabel: "媒体加载中", errorLabel: "媒体加载失败" },
);
const emit = defineEmits<{
  load: [event: Event];
  loadeddata: [event: Event];
  error: [event: Event];
}>();
const loading = ref(true);
const failed = ref(false);

watch(
  () => props.src,
  () => {
    loading.value = true;
    failed.value = false;
  },
  { immediate: true },
);

function finish(event: Event, type: "load" | "loadeddata") {
  loading.value = false;
  failed.value = false;
  if (type === "load") emit("load", event);
  else emit("loadeddata", event);
}

function fail(event: Event) {
  loading.value = false;
  failed.value = true;
  emit("error", event);
}
</script>

<template>
  <img
    v-if="type === 'image'"
    class="loading-media-element"
    v-bind="$attrs"
    :src="src"
    @load="finish($event, 'load')"
    @error="fail"
  />
  <video
    v-else
    class="loading-media-element"
    v-bind="$attrs"
    :src="src"
    @loadeddata="finish($event, 'loadeddata')"
    @error="fail"
  ></video>
  <MediaLoadingState
    v-if="loading || failed"
    :failed="failed"
    :compact="compact"
    :label="loadingLabel"
    :error-label="errorLabel"
  />
</template>

<style scoped>
.loading-media-element {
  display: block;
  max-width: 100%;
  max-height: 100%;
}
</style>
