<template>
  <div class="mark-body">
    <div v-if="markStatus" class="mark-body-status">
      {{ markStatus }}
    </div>
    <div ref="dragContainer" class="mark-body-container">
      <div v-if="!store.currentTask" class="mark-body-none">
        <div>
          <img src="@/assets/image-none-task.png" />
          <p>
            {{ store.message }}
          </p>
        </div>
      </div>
      <div
        v-else-if="store.isScanImage"
        :style="{ width: answerPaperScale }"
        :class="[`rotate-board-${rotateBoard}`]"
      >
        <div
          v-for="(item, index) in sliceImagesWithTrackList"
          :key="index"
          class="single-image-container"
        >
          <img
            :src="item.url"
            draggable="false"
            @click="(event) => innerMakeTrack(event, item)"
            @contextmenu="showBigImage"
          />
          <MarkDrawTrack
            :trackList="item.trackList"
            :specialTagList="item.tagList"
            :sliceImageHeight="item.originalImageHeight"
            :sliceImageWidth="item.originalImageWidth"
            :dx="item.dx"
            :dy="item.dy"
          />
          <hr class="image-seperator" />
        </div>
      </div>
      <div v-else-if="store.isMultiMedia">
        <MultiMediaMarkBody />
      </div>
      <div v-else>未知数据</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, reactive, watch, watchEffect } from "vue";
import { store } from "@/store/store";
import MarkDrawTrack from "../mark/MarkDrawTrack.vue";
import type { SliceImage, SpecialTag, Track } from "@/types";
import { useTimers } from "@/setups/useTimers";
import { loadImage } from "@/utils/utils";
import { dragImage } from "../mark/use/draggable";
import MultiMediaMarkBody from "../mark/MultiMediaMarkBody.vue";
import "viewerjs/dist/viewer.css";
import Viewer from "viewerjs";
// import { message } from "ant-design-vue";
import EventBus from "@/plugins/eventBus";
type MakeTrack = (
  event: MouseEvent,
  item: SliceImage,
  maxSliceWidth: number,
  theFinalHeight: number
) => void | (() => void);

const {
  hasMarkResultToRender = false,
  makeTrack = () => console.debug("非评卷界面makeTrack没有意义"),
} = defineProps<{
  hasMarkResultToRender?: boolean;
  makeTrack?: MakeTrack;
}>();

const emit = defineEmits(["error"]);

//#region : 图片拖动。在轨迹模式下，仅当没有选择分数时可用。
const { dragContainer } = dragImage();
//#endregion : 图片拖动

const { addTimeout } = useTimers();

//#region : 缩略图定位
watch(
  () => [store.minimapScrollToX, store.minimapScrollToY],
  () => {
    const container = document.querySelector<HTMLDivElement>(
      ".mark-body-container"
    );
    addTimeout(() => {
      if (
        container &&
        typeof store.minimapScrollToX === "number" &&
        typeof store.minimapScrollToY === "number"
      ) {
        const { scrollWidth, scrollHeight } = container;
        container.scrollTo({
          top: scrollHeight * store.minimapScrollToY,
          left: scrollWidth * store.minimapScrollToX,
          behavior: "smooth",
        });
      }
    }, 10);
  }
);
//#endregion : 缩略图定位

//#region : 快捷键定位
const scrollContainerByKey = (e: KeyboardEvent) => {
  const container = document.querySelector<HTMLDivElement>(
    ".mark-body-container"
  );
  if (!container) {
    return;
  }
  if (e.key === "w") {
    container.scrollBy({ top: -100, behavior: "smooth" });
  } else if (e.key === "s") {
    container.scrollBy({ top: 100, behavior: "smooth" });
  } else if (e.key === "a") {
    container.scrollBy({ left: -100, behavior: "smooth" });
  } else if (e.key === "d") {
    container.scrollBy({ left: 100, behavior: "smooth" });
  }
};
onMounted(() => {
  document.addEventListener("keypress", scrollContainerByKey);
});
onUnmounted(() => {
  document.removeEventListener("keypress", scrollContainerByKey);
});
//#endregion : 快捷键定位

//#region : 计算裁切图和裁切图上的分数轨迹和特殊标记轨迹
let rotateBoard = $ref(0);
let sliceImagesWithTrackList: SliceImage[] = reactive([]);
let maxImageWidth = 0; // 最大的裁切块宽度，图片容器以此为准
let theFinalHeight = 0; // 最终宽度，用来定位轨迹在第几张图片，不包括image-seperator高度

watch(
  () => sliceImagesWithTrackList,
  () => {
    EventBus.emit("draw-change", sliceImagesWithTrackList);
  },
  { deep: true }
);

const colors = ["red", "blue", "green"];
let colorMap = {};
function addTrackColorAttr(tList: Track[], groupNumber: number): Track[] {
  let userIds: (number | undefined)[] = tList
    .map((v) => v.userId)
    .filter((x) => !!x);
  userIds = Array.from(new Set(userIds));
  const isByMultMark = userIds.length > 1;

  tList = tList.map((item) => {
    const uid = item.userId;
    if (item.headerMarkScore) {
      item.color = "green";
    } else {
      if (!colorMap[groupNumber]) colorMap[groupNumber] = {};
      if (!colorMap[groupNumber][uid]) {
        colorMap[groupNumber][uid] =
          colors[Object.keys(colorMap[groupNumber]).length] || "green";
      }
      item.color = colorMap[groupNumber][uid];
    }
    item.isByMultMark = isByMultMark;
    return item;
  });
  return tList;
}
function addSpecialTrackColorAttr(tList: SpecialTag[]): SpecialTag[] {
  return tList.map((item) => {
    item.color = colorMap[item.groupNumber][item.userId] || "green";
    return item;
  });
}

async function processImage() {
  if (!store.currentTask) return;
  colorMap = {};
  const images = [];
  const urls = store.currentTask.sheetUrls || [];
  for (const url of urls) {
    const image = await loadImage(url);
    images.push(image);
  }

  maxImageWidth = Math.max(...images.map((i) => i.naturalWidth));
  theFinalHeight = Math.max(...images.map((i) => i.naturalHeight));
  sliceImagesWithTrackList.splice(0);

  let trackLists = store.currentTask.questionList
    .map((q) => addTrackColorAttr(q.trackList, q.groupNumber))
    .flat();
  let tagLists = store.currentTask.specialTagList ?? [];
  tagLists = addSpecialTrackColorAttr(tagLists);

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

    const thisImageTrackList = trackLists.filter(
      (t) => t.offsetIndex === indexInSliceUrls
    );
    const thisImageTagList = tagLists.filter(
      (t) => t.offsetIndex === indexInSliceUrls
    );

    sliceImagesWithTrackList.push({
      url,
      indexInSliceUrls,
      trackList: thisImageTrackList,
      tagList: thisImageTagList,
      originalImageWidth: image.naturalWidth,
      originalImageHeight: image.naturalHeight,
      width: (image.naturalWidth / maxImageWidth) * 100 + "%",
      dx: 0,
      dy: 0,
      accumTopHeight,
    });
    accumTopHeight = accumBottomHeight;
  }
}

// should not render twice at the same time
let renderLock = false;
const renderPaperAndMark = async () => {
  // console.log("renderPagerAndMark=>store.curTask:", store.currentTask);

  if (!store.currentTask) return;
  if (!store.isScanImage) return;
  if (renderLock) {
    console.log("上个任务还未渲染完毕，稍等一秒再尝试渲染");
    await new Promise((res) => setTimeout(res, 1000));
    await renderPaperAndMark();
    return;
  }

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

watch(
  () => store.currentTask,
  () => {
    setTimeout(renderPaperAndMark, 50);
  }
);
//#endregion : 计算裁切图和裁切图上的分数轨迹和特殊标记轨迹

//#region : 放大缩小和之后的滚动
const answerPaperScale = $computed(() => {
  // 放大、缩小不影响页面之前的滚动条定位
  let percentWidth = 0;
  let percentTop = 0;
  const container = document.querySelector(".mark-body-container");
  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 + "%";
});
//#endregion : 放大缩小和之后的滚动

//#region : 显示评分状态和清除轨迹
let markStatus = $ref("");
if (hasMarkResultToRender) {
  watch(
    () => store.currentTask,
    () => {
      markStatus = store.getMarkStatus;
    }
  );

  // 清除分数轨迹
  watchEffect(() => {
    for (const track of store.removeScoreTracks) {
      for (const sliceImage of sliceImagesWithTrackList) {
        sliceImage.trackList = sliceImage.trackList.filter(
          (t) =>
            !(
              t.mainNumber === track.mainNumber &&
              t.subNumber === track.subNumber &&
              t.number === track.number
            )
        );
      }
    }
    // 清除后，删除，否则会影响下次切换
    store.removeScoreTracks.splice(0);
  });

  // 清除特殊标记轨迹
  watchEffect(() => {
    if (!store.currentTask) return;
    for (const sliceImage of sliceImagesWithTrackList) {
      sliceImage.tagList = sliceImage.tagList.filter((t) =>
        store.currentTaskEnsured.markResult?.specialTagList.find(
          (st) =>
            st.offsetIndex === t.offsetIndex &&
            st.offsetX === t.offsetX &&
            st.offsetY === t.offsetY
        )
      );
    }
    if (store.currentTaskEnsured.markResult?.specialTagList.length === 0) {
      for (const sliceImage of sliceImagesWithTrackList) {
        sliceImage.tagList = [];
      }
    }
  });
}
//#endregion : 显示评分状态和清除轨迹

//#region : 评分
const innerMakeTrack = (event: MouseEvent, item: SliceImage) => {
  makeTrack(event, item, maxImageWidth, theFinalHeight);
};
//#endregion : 评分

//#region : 显示大图，供查看和翻转
const showBigImage = (event: MouseEvent) => {
  event.preventDefault();
  // console.log(event);
  let viewer: Viewer = null as unknown as Viewer;
  viewer && viewer.destroy();
  viewer = new Viewer(event.target as HTMLElement, {
    // inline: true,
    viewed() {
      viewer.zoomTo(1);
    },
    hidden() {
      viewer.destroy();
    },
    zIndex: 1000000,
  });
  viewer.show();
};
//#endregion : 显示大图，供查看和翻转

// onRenderTriggered(({ key, target, type }) => {
//   console.log({ key, target, type });
// });
let topKB = $ref(10);
// const topKBStyle = $computed(() => topKB + "%");
let leftKB = $ref(10);
// const leftKBStyle = $computed(() => leftKB + "%");
function moveCicle(event: KeyboardEvent) {
  // query mark-body-container and body to calc max/min topKB and max leftKB
  if (event.key === "k") {
    if (topKB > 1) topKB--;
  }
  if (event.key === "j") {
    if (topKB < 99) topKB++;
  }
  if (event.key === "h") {
    if (leftKB > 1) leftKB--;
  }
  if (event.key === "l") {
    if (leftKB < 99) leftKB++;
  }
  if (event.key === "c") {
    topKB = 50;
    leftKB = 50;
  }
}
function giveScoreCicle(event: KeyboardEvent) {
  // console.log(event.key);
  event.preventDefault();
  // console.log(store.currentScore);
  // 接收currentScore间隔时间外才会进入此事件
  if (event.key === " " && typeof store.currentScore === "number") {
    // topKB--;
    const circleElement = document.querySelector(".kb-circle");
    let { top, left } = circleElement.getBoundingClientRect();
    top = top + 45;
    left = left + 45;
    // console.log(top, left);
    // getBoundingClientRect().top left
    // capture => to the specific image
    const me = new MouseEvent("click", {
      bubbles: true,
      cancelable: true,
      view: window,
      clientY: top,
      clientX: left,
    });
    const eles = document.elementsFromPoint(left, top);
    // console.log(eles);
    let ele: Element;
    // if (eles[0].className === "kb-circle") {
    //   if (eles[1].tagName == "IMG") {
    //     ele = eles[1];
    //   }
    // } else
    if (eles[0].tagName == "IMG") {
      ele = eles[0];
    }
    if (ele) {
      ele.dispatchEvent(me);
    }
  }
}
onMounted(() => {
  document.addEventListener("keypress", moveCicle);
  document.addEventListener("keypress", giveScoreCicle);
});
onUnmounted(() => {
  document.removeEventListener("keypress", moveCicle);
  document.removeEventListener("keypress", giveScoreCicle);
});
// setInterval(() => {
//   _topKB++;
//   console.log(topKB);
// }, 1000);

//#region autoScroll自动跳转
let oldFirstScoreContainer: HTMLDivElement | null;
watch(
  () => store.currentTask,
  () => {
    if (store.setting.autoScroll) {
      // 给任务清理和动画留一点时间
      oldFirstScoreContainer =
        document.querySelector<HTMLDivElement>(".score-container");
      oldFirstScoreContainer?.scrollIntoView({ behavior: "smooth" });
      addTimeout(scrollToFirstScore, 1000);
    } else {
      const container = document.querySelector<HTMLDivElement>(
        ".mark-body-container"
      );
      container?.scrollTo({ top: 0, left: 0, behavior: "smooth" });
    }
  }
);
function scrollToFirstScore() {
  if (renderLock) {
    window.requestAnimationFrame(scrollToFirstScore);
  }
  addTimeout(() => {
    const firstScore =
      document.querySelector<HTMLDivElement>(".score-container");
    firstScore?.scrollIntoView({ behavior: "smooth" });
  }, 1000);
}
//#endregion
</script>
