<template>
  <div class="mark-body-container tw-flex-auto tw-p-2" ref="dragContainer">
    <a-spin
      :spinning="rendering"
      size="large"
      tip="Loading..."
      style="margin-top: 50px"
    >
      <div v-if="!store.currentTask" class="tw-text-center">
        {{ store.message }}
      </div>
      <div v-else :style="{ width: answerPaperScale }">
        <div
          v-for="(item, index) in sliceImagesWithTrackList"
          :key="index"
          class="single-image-container"
        >
          <img :src="item.url" draggable="false" />
          <MarkDrawTrack
            :track-list="item.trackList"
            :special-tag-list="item.tagList"
            :original-image-height="item.originalImageHeight"
            :original-image-width="item.originalImageWidth"
          />
          <hr class="image-seperator" />
        </div>
      </div>
    </a-spin>
  </div>
</template>

<script setup lang="ts">
import { computed, reactive, ref, watch } from "vue";
import { store } from "@/features/mark/store";
import MarkDrawTrack from "./MarkDrawTrack.vue";
import type { SpecialTag, Track } from "@/types";
import { useTimers } from "@/setups/useTimers";
import { loadImage } from "@/utils/utils";
import { dragImage } from "@/features/mark/use/draggable";

interface SliceImage {
  url: string;
  trackList: Array<Track>;
  tagList: Array<SpecialTag>;
  originalImageWidth: number;
  originalImageHeight: number;
}

const { usingImage } = withDefaults(
  defineProps<{
    usingImage: "sheetUrls" | "sliceUrls";
  }>(),
  {
    usingImage: "sliceUrls",
  }
);
const emit = defineEmits(["error"]);

const { dragContainer } = dragImage();

const { addTimeout } = useTimers();

let rendering = ref(false);
let sliceImagesWithTrackList: Array<SliceImage> = reactive([]);

async function processImage() {
  if (!store.currentTask) return;

  const images = [];
  const urls = store.currentTask[usingImage] || [];
  for (const url of urls) {
    const image = await loadImage(url);
    images.push(image);
  }

  for (const url of urls) {
    const indexInSliceUrls = urls.indexOf(url) + 1;
    const image = images[indexInSliceUrls - 1];

    const trackLists = (store.currentTask.questionList || [])
      .map((q) => q.trackList)
      .reduce((acc, t) => {
        acc = acc.concat(t);
        return acc;
      }, [] as Array<Track>);
    const thisImageTrackList = trackLists.filter(
      (t) => t.offsetIndex === indexInSliceUrls
    );
    const thisImageTagList = (store.currentTask.specialTagList || []).filter(
      (t) => t.offsetIndex === indexInSliceUrls
    );

    sliceImagesWithTrackList.push({
      url,
      trackList: thisImageTrackList,
      tagList: thisImageTagList,
      originalImageWidth: image.naturalWidth,
      originalImageHeight: image.naturalHeight,
    });
  }
}

// should not render twice at the same time
let renderLock = false;
const renderPaperAndMark = async () => {
  if (renderLock) {
    console.log("上个任务还未渲染完毕，稍等一秒再尝试渲染");
    await new Promise((res) => setTimeout(res, 1000));
    await renderPaperAndMark();
    return;
  }
  renderLock = true;
  sliceImagesWithTrackList.splice(0);

  if (!store.currentTask) {
    renderLock = false;
    return;
  }

  try {
    rendering.value = true;
    await processImage();
  } catch (error) {
    sliceImagesWithTrackList.splice(0);
    console.log("render error ", error);
    // 图片加载出错，自动加载下一个任务
    emit("error");
  } finally {
    renderLock = false;
    rendering.value = false;
  }
};

watch(() => store.currentTask, renderPaperAndMark);

const answerPaperScale = computed(() => {
  // 放大、缩小不影响页面之前的滚动条定位
  let percentWidth = 0;
  let percentTop = 0;
  const container = document.querySelector(
    ".mark-body-container"
  ) as HTMLDivElement;
  if (container) {
    const { scrollLeft, scrollTop, scrollWidth, scrollHeight } = container;
    percentWidth = scrollLeft / scrollWidth;
    percentTop = scrollTop / scrollHeight;
  }

  addTimeout(() => {
    if (container) {
      const { scrollWidth, scrollHeight } = container;
      container.scrollTo({
        left: scrollWidth * percentWidth,
        top: scrollHeight * percentTop,
      });
    }
  }, 10);
  const scale = store.setting.uiSetting["answer.paper.scale"];
  return scale * 100 + "%";
});
</script>

<style scoped>
.mark-body-container {
  height: calc(100vh - 56px);
  overflow: auto;
  background-color: var(--app-container-bg-color);
  background-image: linear-gradient(45deg, #e0e0e0 25%, transparent 25%),
    linear-gradient(-45deg, #e0e0e0 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #e0e0e0 75%),
    linear-gradient(-45deg, transparent 75%, #e0e0e0 75%);
  background-size: 20px 20px;
  background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
  transform: inherit;

  cursor: grab;
  user-select: none;
}
.mark-body-container img {
  width: 100%;
}
.single-image-container {
  position: relative;
}
.image-seperator {
  border: 2px solid rgba(120, 120, 120, 0.1);
}
</style>
