<script setup lang="ts">
import Camera from '@/assets/camera.html?url';
import { DEFAULT_HEIGHT, DEFAULT_WIDTH, DEFAULT_ZOOM } from '@/modules/camera/camera.config';

const {
  preview = true,
  scale = 1,
  offsetX = 0,
  offsetY = 0,
} = defineProps<{
  scale?: number;
  offsetX?: number;
  offsetY?: number;
  preview?: boolean;
}>();
const emits = defineEmits<{ loaded: [] }>();
const style = computed(() => `width: ${scale * DEFAULT_WIDTH}px;height: ${scale * DEFAULT_HEIGHT}px;`);

const snapshot = ref<string | void>();

const cameraFrameRef = useTemplateRef<
  HTMLIFrameElement & {
    contentWindow: {
      loadCamera(props: { width: number; height: number; zoom?: number }): Promise<void>;
      handle(promise?: Promise<void>): string;
      updateCoordinate(offsetX: number, offsetY: number): void;
    };
  }
>('camera-frame');

const loadCamera = async () => {
  await cameraFrameRef.value?.contentWindow.loadCamera?.({
      width: DEFAULT_WIDTH,
      height: DEFAULT_HEIGHT,
      zoom: DEFAULT_ZOOM,
  });

  cameraFrameRef.value?.contentWindow.addEventListener('resize', update);
  emits('loaded');
};

watch([() => offsetX, () => offsetY], () => { setTimeout(update, 100); });

function update() {
  cameraFrameRef.value?.contentWindow.updateCoordinate?.(offsetX, offsetY);
}

defineExpose({
  handle() {
    if ( !preview || !snapshot.value ) {
      snapshot.value = cameraFrameRef.value?.contentWindow.handle?.();
    } else {
      snapshot.value = void 0;
    }
    return snapshot.value;
  },
});
</script>
<template>
  <div class="relative camera-container" :style="style">
    <iframe ref="camera-frame" :src="Camera" @load="loadCamera()"></iframe>
    <img v-if="snapshot" :src="snapshot" alt="图像" />
    <slot name="shade" :style="style" :scale="scale"></slot>
  </div>
</template>
<style scoped lang="scss">
.camera-container {
  iframe {
    clip-path: url('#shade');
  }

  img {
    object-fit: scale-down;
  }

  > * {
    position: absolute;
    width: 100%;
    height: 100%;
  }
}
</style>
