<template>
  <div
    class="remote-screen"
    :class="{ 'remote-screen--dragover': isDragOver }"
    :style="{ aspectRatio: `${imageSink?.resolution?.width ?? 1}/${imageSink?.resolution?.height ?? 1}` }"
    @drop="onDrop"
    @dragover.prevent
    @dragleave="isDragOver = false"
    @dragenter="isDragOver = true"
    @wheel.prevent="onWheel"
    @mousedown="onMouseDown"
  >
    <div class="remote-screen__info">
      {{ screen.name }} ({{ imageSink?.resolution?.width ?? '?' }}x{{ imageSink?.resolution?.height ?? '?' }}) 
      <span style="position:absolute;right:0.25rem;">⚙️</span>
    </div>
    <div class="remote-screen__loading" v-if="isLoading"><span>⟳</span></div>
    <div class="remote-screen__connect" v-if="!screen.isConnected">
      <button @click="screen.connect()">Connect</button>
    </div>
    <canvas
      ref="canvas"
      style="max-width: 100%;"
      :width="imageSink?.resolution?.width / 4"
      :height="imageSink?.resolution?.height / 4"
      :style="{
        // transform: `scale(${scale / 100}) translate(${(x)}%, ${(y)}%)`,
      }"
    />
  </div>
</template>
<script setup lang="ts">
import {computed, inject, ref, watch} from 'vue';
import {ImageSink, RemoteDevice} from '../../model/Remote/types';
import {MountedFsSymbol} from '../../model/injectionSymbols';
import {VirtualFile} from '../../model/FileSystem/types';
import {useLoading} from '../../helpers/withLoading';
import {useMouseDragging} from '../../helpers/mouseDragging';
import {MapLayerDrawable} from '../Map/object';

const props = defineProps<{
  screen: RemoteDevice;
}>();

const imageSink = computed(() => props.screen.imageSink as ImageSink);

const fileSystem = inject(MountedFsSymbol)!;
const canvas = ref<HTMLCanvasElement>();
const isDragOver = ref(false);
const scale = ref(100);

const {isLoading, withLoading} = useLoading();

const {onMouseDown, x, y} = useMouseDragging()

function onWheel(event: WheelEvent) {
  scale.value = Math.max(10, Math.min(1000, scale.value + event.deltaY / 100));
  console.log('scroll', event.deltaY, scale.value);
}

watch(() => [x.value, y.value, scale.value], () => {
  imageSink.value?.transform?.({
    x: x.value,
    y: y.value,
    scale: scale.value / 100,
  });
})

watch(() => imageSink.value?.display, ()=> {
  if (imageSink.value?.display) {
    imageSink.value?.display.connectTarget(canvas.value!);
  }
});


async function drawImage(blob: Blob) {
  if (blob.type.startsWith('image/')) {
    const url = URL.createObjectURL(blob);
    const img = new Image();
    img.onload = () => {
      const ctx = canvas.value!.getContext('2d')!;
      canvas.value!.width = img.width;
      canvas.value!.height = img.height;
      ctx.drawImage(img, 0, 0);
    }
    img.src = url;
  } else if (blob.type.startsWith('video/')) {
    const url = URL.createObjectURL(blob);
    const video = document.createElement('video');
    video.muted = true;
    video.autoplay = true;
    video.src = url;
    video.oncanplaythrough = () => {
      const ctx = canvas.value!.getContext('2d')!;
      canvas.value!.width = video.videoWidth;
      canvas.value!.height = video.videoHeight;
      ctx.drawImage(video, 0, 0);
      video.pause();
    }
  }
}

async function loadFile(meta: VirtualFile, file: File) {
  if (imageSink.value?.display) {
    const map = new MapLayerDrawable(file, meta.map?.width);
    await map.preloadFile();
    imageSink.value.display.mapLayer = map
    console.log(imageSink.value?.display);
  }
  // await withLoading(async () => {
  //   await Promise.all([
  //     imageSink.value?.transferFile(meta, file),
  //     drawImage(file),
  //   ])
  //   await imageSink.value?.show(meta);
  // })
}

async function onDrop(event: DragEvent) {
  event.preventDefault();
  isDragOver.value = false;
  const file = event.dataTransfer?.files?.[0];
  if (file) {
    const meta = {
      type: 'file',
      source: 'drop',
      path: [] as string[],
      name: file.name,
      mimeType: file.type
    } as const;
    await loadFile(meta, file)
  } else if (event.dataTransfer?.getData('application/json')) {
    const meta = JSON.parse(event.dataTransfer?.getData('application/json'));
    if (meta.type === 'file') {
      const file = await fileSystem.download(meta);
      await loadFile(meta, file);
    }
  }
  console.log('files', event.dataTransfer?.files);
  console.log('drop', event.dataTransfer?.getData('application/json'));
}

</script>
<style>
@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.remote-screen {
  position: relative;
  display: inline-block;
  border: 2px solid white;
  border-radius: 4px;
  background-color: black;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  max-height: 100%;
}

.remote-screen__info {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background-color: rgba(0, 0, 0, 0.5);
  padding: 4px;
  text-align: center;
}

.remote-screen__loading {
  pointer-events: none;
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  color: white;
  background-color: rgba(0, 0, 0, 0.5);

  span {
    transform-origin: 44% 54%;
    animation: spin 1000ms linear infinite;
  }
}

.remote-screen__connect {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: rgba(0, 0, 0, 0.5);
  padding: 4px;
  text-align: center;
}

.remote-screen--dragover {
  border-color: orange;
}
</style>
