<template>
  <video
    v-if="type ===  'video'"
    :src="src"
    :style="dynamicStyle"
    class="map-scene--video map-scene"
    ref="video"
    @loadedmetadata="onVideoLoaded"
    autoplay
    loop
    muted
  ></video>
  <canvas
    v-else
    :style="dynamicStyle"
    ref="canvas"
    class="map-scene--image map-scene"
  />
</template>
<script setup lang="ts">
import { computed, defineProps, inject, ref, watch } from 'vue';
import {ReceiverSymbol} from '../../model/injectionSymbols';

const video = ref<HTMLVideoElement>();
const canvas = ref<HTMLCanvasElement>();

const props = defineProps<{
  src?: string;
  width: number;
  dpi: number;
  position: {x: number, y: number};
  flipped: boolean;
}>();

const isImage = computed(() => props.src?.endsWith('.png') || props.src?.endsWith('.jpg') || props.src?.endsWith('.jpeg') || props.src?.endsWith('.webp'));
const isVideo = computed(() => props.src?.endsWith('.mp4') || props.src?.endsWith('.webm'));

const mediaDimensions = ref({width: 0, height: 0});


watch(() => props.src, (src) => {
  if (isImage.value) {
    const img = new Image();
    img.src = src!;
    img.onload = () => {
      mediaDimensions.value = {
        width: img.naturalWidth,
        height: img.naturalHeight,
      };
      canvas.value!.width = img.naturalWidth;
      canvas.value!.height = img.naturalHeight;
      const ctx = canvas.value!.getContext('2d')!;
      ctx.drawImage(img, 0, 0);
      
    };
  } else if (isVideo.value) {
    video.value!.src = src!;
  }
});

const receiver = inject(ReceiverSymbol);
receiver?.addEventListener('streamImage', ({detail}) => {
  if (canvas.value) {
    if (canvas.value.width !== detail.canvas.width || canvas.value.height !== detail.canvas.height) {
      const backup = document.createElement('canvas');
      backup.width = canvas.value.width;
      backup.height = canvas.value.height;
      const backupCtx = backup.getContext('2d')!;
      backupCtx.drawImage(canvas.value, 0, 0);
      canvas.value.width = detail.canvas.width;
      canvas.value.height = detail.canvas.height;
      const ctx = canvas.value.getContext('2d')!;
      ctx.drawImage(backup, 0, 0, detail.canvas.width, detail.canvas.height);
    }

    const imageData = new ImageData(
      new Uint8ClampedArray(new Uint32Array(detail.imageData.data).buffer),
      detail.imageData.width,
      detail.imageData.height
    );
    const ctx = canvas.value.getContext('2d')!;
    ctx.putImageData(imageData, detail.x, detail.y);
  }
});


const type = computed(() => {
  if (isImage.value) {
    return 'image';
  } else if (isVideo.value) {
    return 'video';
  } else {
    return 'unknown';
  }
});

const dynamicStyle = computed(() => {
  const width = props.dpi * props.width;
  return {
    '--width': `${width}px`,
    '--height': `${(width) * (mediaDimensions.value.height / mediaDimensions.value.width)}px`,
    '--x': `${props.position.x/100}`,
    '--y': `${props.position.y/100}`,
    '--rotate': mediaDimensions.value.width > mediaDimensions.value.height ? (props.flipped ? '180deg' : '0deg') : 
      (props.flipped ? '90deg' : '-90deg'),
  };
});


function onVideoLoaded() {
  mediaDimensions.value = {
    width: video.value!.videoWidth,
    height: video.value!.videoHeight,
  };
}

</script>
<style>
.map-scene {
  position: absolute;
  left: calc(var(--x) * 100vw - var(--width) / 2);
  top: calc(var(--y) * 100vh - var(--height) / 2);
  width: var(--width);
  transform: rotate(var(--rotate));
  transform-origin: center;
}
</style>