<template>
  <div class="mark-body-container flex-auto" ref="container">
    <div v-if="!store.currentTask" class="text-center">暂无评卷任务</div>
    <div v-else :style="{ width: answerPaperScale }">
      <div
        v-for="(item, index) in sliceImagesWithTrackList"
        :key="index"
        class="single-image-container"
      >
        <img
          :src="item.url"
          @click="(event) => makeMark(event, item)"
          draggable="false"
        />
        <MarkDrawTrack
          :track-list="item.trackList"
          :original-image="item.originalImage"
          :slice-image="item.sliceImage"
          :dx="item.dx"
          :dy="item.dy"
        />
        <hr style="border: 2px solid grey" />
      </div>
      <!-- style="border: 1px solid black; background: black" -->
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, reactive, ref, watchEffect } from "vue";
import { findCurrentTaskMarkResult, store } from "./store";
import filters from "@/filters";
import MarkDrawTrack from "./MarkDrawTrack.vue";
import { MarkResult, Track } from "@/types";

interface SliceImage {
  url: string;
  indexInSliceUrls: number;
  trackList: Array<Track>;
  originalImage: HTMLImageElement;
  sliceImage: HTMLImageElement;
  dx: number;
  dy: number;
  accumTopHeight: number;
}
export default defineComponent({
  name: "MarkBody",
  components: { MarkDrawTrack },
  setup(props, context) {
    const container = ref(null);
    let sliceImagesWithTrackList: Array<SliceImage> = reactive([]);
    let maxSliceWidth = 0;
    let theFinalHeight = 0;

    const renderPaperAndMark = async () => {
      async function loadImage(url: string): Promise<HTMLImageElement> {
        return new Promise((resolve, reject) => {
          const image = new Image();
          image.setAttribute("crossorigin", "anonymous");
          image.src = url;
          image.onload = () => resolve(image);
          image.onerror = reject;
        });
      }
      if (!store.currentTask?.libraryId) {
        return;
      }

      // check if have MarkResult for currentTask
      let markResult = findCurrentTaskMarkResult();
      // console.log("watcheffect markResult 1", markResult, store.markResults);

      if (!markResult && store.currentTask) {
        const { libraryId, studentId } = store.currentTask;
        const statusValue = store.setting.statusValue;
        markResult = {} as MarkResult;
        markResult.libraryId = libraryId;
        markResult.studentId = studentId;
        markResult.statusValue = statusValue;
        markResult.spent = Date.now();

        markResult.trackList = store.currentTask.questionList.reduce(
          (all, c) => all.concat(c.trackList),
          [] as Array<Track>
        );
        store.markResults = [...store.markResults, markResult];
        // console.log("watcheffect markResult 2", markResult, store.markResults);
      }
      // store.markResults.splice(store.markResults.indexOf(markResult), 1);
      // store.markResults.push(markResult);
      // console.log("watcheffect markResult 3", markResult, store.markResults);
      // const allTrackList = findCurrentTaskMarkResult().trackList;
      // console.log(allTrackList);
      // console.log(store.markResults);

      // reset sliceImagesWithTrackList
      sliceImagesWithTrackList.splice(0);

      if (store.currentTask.sliceConfig?.length) {
        for (const url of store.currentTask.sliceUrls) {
          await loadImage(filters.toCompleteUrl(url));
        }
        theFinalHeight = store.currentTask.sliceConfig
          .map((v) => v.h)
          .reduce((acc, v) => (acc += v));
        let accumTopHeight = 0;
        let accumBottomHeight = 0;
        for (const sliceConfig of store.currentTask.sliceConfig) {
          accumBottomHeight += sliceConfig.h;
          const url = filters.toCompleteUrl(
            store.currentTask.sliceUrls[sliceConfig.i - 1]
          );
          const image = await loadImage(url);

          const div = (container.value as unknown) as HTMLDivElement;
          maxSliceWidth = Math.max(
            ...store.currentTask.sliceConfig.map((v) => v.w)
          );

          const canvas = document.createElement("canvas");
          // canvas.width = sliceConfig.w;
          canvas.width = Math.max(sliceConfig.w, maxSliceWidth);
          canvas.height = sliceConfig.h;
          const ctx = canvas.getContext("2d");
          // drawImage 画图软件透明色
          ctx?.drawImage(
            image,
            sliceConfig.x,
            sliceConfig.y,
            sliceConfig.w,
            sliceConfig.h,
            0,
            0,
            sliceConfig.w,
            sliceConfig.h
          );
          // console.log(image, canvas.height, sliceConfig, ctx);
          // console.log(canvas.toDataURL());
          const thisImageTrackList = markResult.trackList.filter(
            (v) => v.offsetIndex === sliceConfig.i
          );

          const dataUrl = canvas.toDataURL();
          const sliceImage = new Image();
          sliceImage.src = dataUrl;
          // sliceConfig.x + sliceConfig.w
          sliceImagesWithTrackList.push({
            url: dataUrl,
            indexInSliceUrls: sliceConfig.i,
            // 通过positionY来定位是第几张slice的还原，并过滤出相应的track
            trackList: thisImageTrackList.filter(
              (t) =>
                t.positionY >= accumTopHeight / theFinalHeight &&
                t.positionY < accumBottomHeight / theFinalHeight
            ),
            originalImage: image,
            sliceImage,
            dx: sliceConfig.x,
            dy: sliceConfig.y,
            accumTopHeight,
          });
          accumTopHeight = accumBottomHeight;
        }
      } else {
        const images = [];
        for (const url of store.currentTask.sliceUrls) {
          const image = await loadImage(filters.toCompleteUrl(url));
          images.push(image);
        }

        // TODO: add loading
        const newConfig = (store.setting.splitConfig
          .map((v, index, ary) =>
            index % 2 === 0 ? [v, ary[index + 1]] : false
          )
          .filter((v) => v) as unknown) as Array<[number, number]>;

        const maxSplitConfig = Math.max(...store.setting.splitConfig);
        maxSliceWidth =
          Math.max(...images.map((v) => v.naturalWidth)) * maxSplitConfig;

        theFinalHeight =
          newConfig.length *
          images.reduce((acc, v) => (acc += v.naturalHeight), 0);

        let accumTopHeight = 0;
        let accumBottomHeight = 0;
        for (const url of store.currentTask.sliceUrls) {
          const completeUrl = filters.toCompleteUrl(url);

          for (const config of newConfig) {
            const image = await loadImage(completeUrl);

            accumBottomHeight += image.naturalHeight;
            const div = (container.value as unknown) as HTMLDivElement;

            const width = image.naturalWidth * (config[1] - config[0]);
            const canvas = document.createElement("canvas");
            canvas.width = Math.max(width, maxSliceWidth);
            canvas.height = image.naturalHeight;
            const ctx = canvas.getContext("2d");
            // drawImage 画图软件透明色
            ctx?.drawImage(
              image,
              image.naturalWidth * config[0],
              0,
              image.naturalWidth * config[1],
              image.naturalHeight,
              0,
              0,
              image.naturalWidth * config[1],
              image.naturalHeight
            );
            // console.log(image, canvas.height, sliceConfig, ctx);
            // console.log(canvas.toDataURL());

            const thisImageTrackList = markResult.trackList.filter(
              (t) =>
                t.offsetIndex === store.currentTask.sliceUrls.indexOf(url) + 1
            );

            const dataUrl = canvas.toDataURL();
            const sliceImage = new Image();
            sliceImage.src = dataUrl;
            sliceImagesWithTrackList.push({
              url: canvas.toDataURL(),
              indexInSliceUrls: store.currentTask.sliceUrls.indexOf(url) + 1,
              trackList: thisImageTrackList.filter(
                (t) =>
                  t.positionY >= accumTopHeight / theFinalHeight &&
                  t.positionY < accumBottomHeight / theFinalHeight
              ),
              originalImage: image,
              sliceImage,
              dx: image.naturalWidth * config[0],
              dy: 0,
              accumTopHeight,
            });
            accumTopHeight = accumBottomHeight;
          }
        }
      }
    };

    watchEffect(renderPaperAndMark);

    // const reRenderPaperAndMark = () => {
    //   // const markResult = findCurrentTaskMarkResult();
    //   // const thisImageTrackList = markResult.trackList.filter(
    //   //       (v) => v.offsetIndex === sliceConfig.i
    //   //     );
    //   sliceImagesWithTrackList;
    // };
    // watch(() => store.markResults, reRenderPaperAndMark, { deep: true });

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

      setTimeout(() => {
        if (document.querySelector(".mark-body-container")) {
          const container = document.querySelector(
            ".mark-body-container"
          ) as HTMLDivElement;
          const scrollWidth = container.scrollWidth;
          const scrollHeight = container.scrollHeight;
          container.scrollTo({
            left: scrollWidth * percentWidth,
            top: scrollHeight * percentTop,
          });
        }
      }, 10);
      const scale = store.setting.uiSetting["answer.paper.scale"] || 1;
      return scale * 100 + "%";
    });

    const makeMark = (event: MouseEvent, item: SliceImage) => {
      // console.log(event);
      // console.log(item);
      const target = event.target as HTMLImageElement;
      const track = {} as Track;
      // TODO: choose question first
      track.mainNumber = 4;
      track.subNumber = "1";
      track.number = 0;
      track.score = 2;
      track.offsetIndex = item.indexInSliceUrls;
      track.offsetX = Math.round(
        event.offsetX * (target.naturalWidth / target.width) + item.dx
      );
      track.offsetY = Math.round(
        event.offsetY * (target.naturalHeight / target.height) + item.dy
      );
      track.positionX = (track.offsetX - item.dx) / maxSliceWidth;
      track.positionY =
        (track.offsetY - item.dy + item.accumTopHeight) / theFinalHeight;
      // console.log(track);
      const markResult = findCurrentTaskMarkResult();
      // console.log("makemark markresult", markResult);
      if (markResult) {
        markResult.trackList = [...markResult.trackList, track];
      }
      // sliceImagesWithTrackList.find(s => s.indexInSliceUrls === item.indexInSliceUrls)
      item.trackList.push(track);
    };
    return {
      container,
      store,
      sliceImagesWithTrackList,
      answerPaperScale,
      makeMark,
    };
  },
});
</script>

<style scoped>
.mark-body-container {
  height: calc(100vh - 41px);
  overflow: scroll;
  background-size: 8px 8px;
  background-image: linear-gradient(to right, #e7e7e7 4px, transparent 4px),
    linear-gradient(to bottom, transparent 4px, #e7e7e7 4px);
}
.mark-body-container img {
  width: 100%;
}
.single-image-container {
  position: relative;
}
</style>
