<template>
  <div
    v-if="store.currentTask"
    class="mark-board-track"
    :class="[
      {
        hide: store.isScoreBoardCollapsed && !props.modal,
        'in-dialog': store.isScoreBoardCollapsed && props.modal,
      },
    ]"
    :style="{
      height: props.modal ? '100%' : 'auto',
    }"
  >
    <div class="board-header">
      <div class="board-header-left">
        <div class="board-header-info">
          <img src="@/assets/icons/icon-star.svg" />
          <span>总分</span>
        </div>
        <div class="board-header-score">
          <transition-group name="score-number-animation" tag="span">
            <span :key="store.currentTask.markResult?.markerScore || 0">{{
              store.currentTask.markResult?.markerScore
            }}</span>
          </transition-group>
        </div>
      </div>
      <qm-button
        class="board-header-submit"
        size="medium"
        type="primary"
        @click="submit"
      >
        提交
      </qm-button>
    </div>
    <div
      v-if="store.currentTask && store.currentTask.questionList"
      class="board-questions"
      :style="{
        height: areaHeight ? `${areaHeight}px` : 'auto',
        flexGrow: areaHeight ? 0 : 2,
      }"
    >
      <template
        v-for="(question, index) in store.currentTask.questionList"
        :key="index"
      >
        <div class="board-question-box">
          <div
            :id="
              store.isScoreBoardCollapsed
                ? props.modal
                  ? ['bq', question.mainNumber, question.subNumber].join('-')
                  : ''
                : ['bq', question.mainNumber, question.subNumber].join('-')
            "
            :class="[
              'board-question',
              { 'is-current': isCurrentQuestion(question) },
            ]"
            tabindex="0"
            outline="0"
            hidefocus="true"
            @click="chooseQuestion(question)"
            @contextmenu="onRightClick($event, index)"
            @blur="rightBlur"
          >
            <div
              v-if="
                activeRightMenuItem?.id ==
                (store.isScoreBoardCollapsed
                  ? props.modal
                    ? ['bq', question.mainNumber, question.subNumber].join('-')
                    : ''
                  : ['bq', question.mainNumber, question.subNumber].join('-'))
              "
              class="tw-fixed right-menu-box"
              :style="tmpStyle"
            >
              <div class="right-menu-item" @click="positioning(question)">
                定位
              </div>
            </div>
            <div class="question-info">
              <div class="question-title" :title="question.title">
                {{ question.title }}
              </div>
              <div class="question-no">
                {{ question.mainNumber }}-{{ question.subNumber }}
              </div>
            </div>
            <!-- 设置高度 避免动画跳动 -->
            <div class="question-score">
              <transition-group name="score-number-animation" tag="span">
                <span
                  :key="store.currentTask?.markResult?.scoreList[index] || 0"
                >
                  <!-- 特殊的空格符号 -->
                  <!-- eslint-disable-next-line no-irregular-whitespace -->
                  {{ store.currentTask?.markResult?.scoreList[index] ?? " " }}
                </span>
              </transition-group>
            </div>
          </div>
        </div>
      </template>
    </div>
    <div class="board-spliter">
      <div class="board-spliter-up" @click="areaHeight = 74">
        <img src="@/assets/icons/icon-up.svg" />
        <img src="@/assets/icons/icon-up-active.svg" />
      </div>
      <div ref="dragSpliter" class="board-spliter-bar"></div>
      <div class="board-spliter-down" @click="areaHeight = 0">
        <img src="@/assets/icons/icon-down.svg" />
        <img src="@/assets/icons/icon-down-active.svg" />
      </div>
    </div>
    <div v-if="!questionScoreDisabled" class="board-scores">
      <div
        v-for="(s, i) in questionScoreSteps.slice(1)"
        :key="i"
        :class="['board-score', { 'is-current': isCurrentScore(s) }]"
        @click="chooseScore(s)"
      >
        {{ s }}
      </div>
      <div
        class="board-score"
        :class="Object.is(store.currentScore, 0) && 'is-current'"
        @click="chooseScore(0)"
      >
        0
      </div>
    </div>
    <div class="board-footer">
      <div>
        <qm-button
          v-if="!questionScoreDisabled"
          class="board-goback"
          :clickTimeout="300"
          @click="clearLatestMarkOfCurrentQuetion"
        >
          <template #icon>
            <img src="@/assets/icons/icon-goback.svg" />
          </template>
          回退
        </qm-button>
      </div>

      <qm-button
        class="board-clear"
        :clickTimeout="300"
        data-test="clear-score"
        @click="clearAllMarksOfCurrentQuetion"
      >
        <template #icon>
          <img class="icon-common" src="@/assets/icons/icon-clear.svg" />
          <img class="icon-active" src="@/assets/icons/icon-clear-white.svg" />
        </template>
        清空
      </qm-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { Question } from "@/types";
import { isNumber } from "lodash-es";
import { onMounted, onUnmounted, watch, ref, reactive } from "vue";
import { store } from "@/store/store";
import { autoChooseFirstQuestion } from "./use/autoChooseFirstQuestion";
import { dragSplitPane } from "./use/splitPane";
import { addFocusTrack, removeFocusTrack } from "./use/focusTracks";
import EventBus from "@/plugins/eventBus";
import { cloneDeep } from "lodash-es";

const props = defineProps<{ modal?: boolean; isCheckAnswer?: boolean }>();
const emit = defineEmits(["submit", "unselectiveSubmit"]);
const { dragSpliter, areaHeight } = dragSplitPane();
const activeRightMenuItem = ref<any>(null);
const tmpStyle = reactive<any>({
  left: 0,
  top: 0,
  zIndex: 300,
});
function getParentNode(el: any, c: string): any {
  if (el.className?.includes(c)) {
    return el;
  } else {
    if (el.parentNode) {
      return getParentNode(el.parentNode, c);
    } else {
      return null;
    }
  }
}
const onRightClick = (e: any, index?: any) => {
  e.preventDefault();
  if (
    store.currentTask?.markResult.scoreList[index] ||
    store.currentTask?.markResult.scoreList[index] === 0
  ) {
    tmpStyle.left = e.clientX + "px";
    tmpStyle.top = e.clientY + "px";
    let parentNode = getParentNode(e.target, "board-question");
    if (parentNode) {
      activeRightMenuItem.value = parentNode;
    }
    console.log("activeRightMenuItem:", activeRightMenuItem.value);
  }
};
const rightBlur = () => {
  activeRightMenuItem.value = null;
  removeFocusTrack();
};
const positioning = (question: Question) => {
  // let list =
  //   store.getMarkStatus === "正评" || store.getMarkStatus === "试评"
  //     ? sliceImagesWithTrackListCopy.value
  //     : undefined;
  // addFocusTrack(undefined, question.mainNumber, question.subNumber, true, list);
  console.log(
    "sliceImagesWithTrackListCopy:",
    sliceImagesWithTrackListCopy.value
  );
  addFocusTrack(
    undefined,
    question.mainNumber,
    question.subNumber,
    true,
    sliceImagesWithTrackListCopy.value || []
  );
  activeRightMenuItem.value = null;
};

const { chooseQuestion } = autoChooseFirstQuestion();
let sliceImagesWithTrackListCopy = ref([]);
EventBus.on("draw-change", (list: any) => {
  sliceImagesWithTrackListCopy.value = cloneDeep(list);
});

// 切换题目是清空上一题的分数
watch(
  () => store.currentQuestion,
  () => {
    store.currentScore = undefined;
    if (!props.isCheckAnswer) chooseScore(questionScoreSteps[1]);
  }
);

watch(
  () => store.currentTask,
  () => {
    if (!props.isCheckAnswer) return;

    let currentTaskModifyQuestion = {};
    store.currentTask.questionList.forEach((q) => {
      const qno = `${q.mainNumber}_${q.subNumber}`;
      currentTaskModifyQuestion[qno] = false;
    });
    store.currentTaskModifyQuestion = currentTaskModifyQuestion;
  }
);

const questionScoreDisabled = $computed(() => {
  const qno = `${store.currentQuestion.mainNumber}_${store.currentQuestion.subNumber}`;
  return props.isCheckAnswer && !store.currentTaskModifyQuestion[qno];
});

const questionScore = $computed(
  () =>
    store.currentTask &&
    store.currentQuestion &&
    store.currentTask.markResult?.scoreList[store.currentQuestion.__index]
);

const questionScoreSteps = $computed(() => {
  const question = store.currentQuestion;
  if (!question) return [];

  const remainScore =
    Math.round(question.maxScore * 1000 - (questionScore || 0) * 1000) / 1000;

  const steps = [];
  if (question.intervalScore <= 0) {
    console.warn(`question.intervalScore got: ${question.intervalScore}`);
  }
  for (
    let i = 0;
    i <= remainScore && question.intervalScore > 0;
    i = Math.round(i * 1000 + question.intervalScore * 1000) / 1000
  ) {
    steps.push(i);
  }
  if (
    Math.round(remainScore * 1000) %
      Math.round(question.intervalScore * 1000) !==
    0
  ) {
    steps.push(remainScore);
  }

  return steps;
});

function isCurrentQuestion(question: Question) {
  return (
    store.currentQuestion?.mainNumber === question.mainNumber &&
    store.currentQuestion?.subNumber === question.subNumber
  );
}

function isCurrentScore(score: number) {
  return store.currentScore === score;
}
function chooseScore(score: number) {
  if (store.currentScore === score) {
    store.currentScore = undefined;
  } else {
    store.currentScore = score;
    store.currentSpecialTag = undefined;
  }
  store.currentSpecialTagType = undefined;
}

let keyPressTimestamp = 0;
let keys: string[] = [];
function numberKeyListener(event: KeyboardEvent) {
  // if (event.target.tagName !== "BODY") return;
  if (!store.currentQuestion) return;
  if (questionScoreDisabled) return;
  if (" jiklc".includes(event.key)) return;
  // if (event.key === "#") {
  //   keys = [];
  //   store.currentScore = -0;
  //   return;
  // }

  function indexOfCurrentQuestion() {
    return (
      store.currentTask?.questionList.findIndex(
        (q) =>
          q.mainNumber === store.currentQuestion?.mainNumber &&
          q.subNumber === store.currentQuestion.subNumber
      ) ?? -1
    );
  }

  // tab 循环答题列表
  if (event.key === "Tab") {
    const idx = indexOfCurrentQuestion();
    if (idx >= 0 && store.currentTask) {
      const len = store.currentTask.questionList.length;
      chooseQuestion(store.currentTask.questionList[(idx + 1) % len]);
      event.preventDefault();
    }
    return;
  }

  // 为了cypress可以加速时间
  if (Date.now() - keyPressTimestamp > 1 * 1000) {
    keys = [];
  }
  keyPressTimestamp = Date.now();
  keys.push(event.key);
  if (isNaN(parseFloat(keys.join("")))) {
    keys = [];
  }
  if (event.key === "Escape") {
    keys = [];
    store.currentScore = undefined;
    store.currentSpecialTag = undefined;
    return;
  }
  const score = parseFloat(keys.join(""));
  if (isNumber(score) && questionScoreSteps.includes(score)) {
    chooseScore(score);
  }
}

function submitListener(e: KeyboardEvent) {
  // if (event.target.tagName !== "BODY") return;
  // if (import.meta.env.DEV && e.ctrlKey && e.key === "Enter") {
  if (e.ctrlKey && e.key === "Enter") {
    submit();
  }
}
onMounted(() => {
  document.addEventListener("keydown", numberKeyListener);
  document.addEventListener("keydown", submitListener);
});
onUnmounted(() => {
  document.removeEventListener("keydown", numberKeyListener);
  document.removeEventListener("keydown", submitListener);
});

watch(
  () => store.isScoreBoardCollapsed,
  () => {
    // 此处的逻辑是 MarkBoardTrackDialog 带来的，不然 numberKeyListener 在两个组件中多次触发有问题
    if (store.isScoreBoardCollapsed) {
      document.removeEventListener("keydown", numberKeyListener);
      document.removeEventListener("keydown", submitListener);
    } else {
      // 重复添加相同的function是没问题，不会重复触发
      document.addEventListener("keydown", numberKeyListener);
      document.addEventListener("keydown", submitListener);
    }
  },
  { immediate: true }
);

function clearLatestMarkOfCurrentQuetion() {
  if (!store.currentTask?.markResult || !store.currentQuestion) return;

  const { __index, mainNumber, subNumber } = store.currentQuestion;
  const markResult = store.currentTask.markResult;
  const ts = markResult.trackList.filter(
    (q) => q.mainNumber === mainNumber && q.subNumber === subNumber
  );
  console.log(ts);

  if (ts.length === 0) {
    return;
  }
  const lastMark = ts.splice(-1)[0];
  store.removeScoreTracks = [lastMark];
  markResult.trackList = markResult.trackList.filter((t) => t !== lastMark);

  markResult.scoreList[__index] =
    ts.length === 0
      ? null
      : ts
          .map((t) => t.score)
          .reduce((acc, v) => (acc += Math.round(v * 1000)), 0) / 1000;
}

function clearAllMarksOfCurrentQuetion() {
  if (!store.currentTask?.markResult || !store.currentQuestion) return;

  const qno = `${store.currentQuestion.mainNumber}_${store.currentQuestion.subNumber}`;
  store.currentTaskModifyQuestion[qno] = true;

  const markResult = store.currentTask.markResult;
  store.removeScoreTracks = markResult.trackList.filter(
    (q) =>
      q.mainNumber === store.currentQuestion?.mainNumber &&
      q.subNumber === store.currentQuestion?.subNumber
  );
  markResult.trackList = markResult.trackList.filter(
    (q) => !store.removeScoreTracks.includes(q)
  );
  const { __index } = store.currentQuestion;
  markResult.scoreList[__index] = null;
}

function submit() {
  emit("submit");
}
</script>

<style lang="less" scoped>
.right-menu-box {
  z-index: 10;
  background-color: #fff;
  border-radius: 4px;
  width: 80px;
  padding: 2px 0;
  box-shadow: 0 0 3px #ddd;

  .right-menu-item {
    height: 30px;
    line-height: 30px;
    font-size: 14px;
    padding: 0 10px;
    color: #333;
    &:hover {
      background: var(--app-main-bg-color);
    }
  }
}
</style>
