<template>
  <div
    v-if="store.currentTask"
    class="mark-board-track is-key-board"
    :class="[store.isScoreBoardCollapsed ? 'hide' : 'show']"
  >
    <div class="board-mode">
      <a-dropdown>
        <template #overlay>
          <a-menu>
            <a-menu-item key="1" @click="toggleKeyMouse">
              鼠标给分
            </a-menu-item>
          </a-menu>
        </template>
        <a-button>
          键盘给分
          <DownOutlined style="display: inline-flex" />
        </a-button>
      </a-dropdown>
    </div>
    <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.currentTaskEnsured.questionList"
      class="board-questions"
      :style="{
        flexGrow: 2,
      }"
    >
      <template
        v-for="(question, index) in store.currentTaskEnsured.questionList"
        :key="index"
      >
        <div class="board-question-full-box">
          <div
            :id="'bq-' + question.mainNumber + '-' + question.subNumber"
            :class="[
              'board-question',
              { 'is-current': isCurrentQuestion(question) },
            ]"
            @click="
              () => {
                chooseQuestion(question);
                scrollToQuestion(question);
              }
            "
          >
            <div class="question-info">
              <div class="question-title" :title="question.title">
                {{ question.title }}
              </div>
              <div class="question-no">
                间隔{{ question.intervalScore }}分，给分区间{{
                  question.minScore
                }}~{{ question.maxScore }}
              </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>
</template>

<script setup lang="ts">
import type { Question } from "@/types";
import { isNumber } from "lodash-es";
import { onMounted, onUnmounted, watch } from "vue";
import { store } from "@/store/store";
import { keyMouse } from "./use/keyboardAndMouse";
import { autoChooseFirstQuestion } from "./use/autoChooseFirstQuestion";
import { message } from "ant-design-vue";
import { DownOutlined } from "@ant-design/icons-vue";

const emit = defineEmits(["submit", "allZeroSubmit", "unselectiveSubmit"]);

const { toggleKeyMouse } = keyMouse();
const { chooseQuestion } = autoChooseFirstQuestion();

/**
 * 当前题的输入串，初次是markResult.scoreList中score，然后接收输入字符，回车时判断是否合法，合法则赋值给markResult.scoreList
 * 切换到下一题，则重新开始
 *  */
let scoreStr = $ref("");
watch(
  () => [store.currentQuestion, store.setting.uiSetting["normal.mode"]],
  () => {
    if (isNumber(store.currentQuestion?.score)) {
      scoreStr = "" + store.currentQuestion?.score;
    } else {
      scoreStr = "";
    }
  },
  { immediate: true }
);

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

  const remainScore = Math.round(question.maxScore * 100) / 100;
  const steps = [];
  for (
    let i = 0;
    i <= remainScore;
    i = Math.round(i * 100 + question.intervalScore * 100) / 100
  ) {
    steps.push(i);
  }
  if (
    Math.round(remainScore * 100) % Math.round(question.intervalScore * 100) !==
    0
  ) {
    steps.push(remainScore);
  }

  return steps;
});

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

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

function numberKeyListener(event: KeyboardEvent) {
  // console.log(event);
  if (!store.currentQuestion || !store.currentTask) return;
  if (store.globalMask) return;

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

  // 处理Enter跳下一题或submit
  if (event.key === "Enter") {
    const allScoreMarked = store.currentTask.markResult.scoreList.every((s) =>
      isNumber(s)
    );
    // 如果所有题已赋分，并且当前题赋分和输入串和当前题分数一致，则可以在任意题提交
    if (allScoreMarked && scoreStr === "" + questionScore) {
      submit();
      return;
    }

    if (scoreStr.length === 0) {
      void message.error({ content: "请输入分数", duration: 5 });
      console.log("请输入分数");
      return;
    }

    // 0 分
    // 整数分 (开始不为0)
    // 小数分 (开始和结束不为0，结束必须为1-9
    if (
      !(
        scoreStr === "0" ||
        /^0\.[1-9]\d*$/.test(scoreStr) ||
        /^[1-9]\d*$/.test(scoreStr) ||
        /^[1-9]\d*\.\d*[1-9]$/.test(scoreStr)
      )
    ) {
      void message.error({ content: "分数格式不正确", duration: 5 });
      console.log("分数格式不正确");
      return;
    }
    const score = parseFloat(scoreStr);
    // console.log(score);
    if (!isNumber(score)) {
      void message.error({ content: "非数字输入", duration: 5 });
      console.log("非数字输入");
      return;
    }
    if (!questionScoreSteps.includes(score)) {
      void message.error({ content: "输入的分数不在有效间隔内", duration: 5 });
      return;
    }
    const { __index } = store.currentQuestion;
    store.currentTask.markResult.scoreList[__index] = score;
    //
    // scoreStr = "";
    // console.log("give score", score);
    const idx = indexOfCurrentQuestion();
    if (idx + 1 < store.currentTask.questionList.length) {
      chooseQuestion(store.currentTask.questionList[idx + 1]);
    }
    return;
  }
  if (event.key === "ArrowUp") {
    const idx = indexOfCurrentQuestion();
    if (idx > 0) {
      chooseQuestion(store.currentTask.questionList[idx - 1]);
    }
    event.preventDefault();
    return;
  }
  if (event.key === "ArrowDown") {
    const idx = indexOfCurrentQuestion();
    if (idx < store.currentTask.questionList.length - 1) {
      chooseQuestion(store.currentTask.questionList[idx + 1]);
    }
    event.preventDefault();
    return;
  }
  // 处理回退删除分数
  if (event.key === "Backspace") {
    if (scoreStr.length > 0) {
      scoreStr = scoreStr.slice(0, -1);
    } else {
      return;
    }
  }
  if (event.key === "Escape") {
    scoreStr = "";
  }

  // 此时不再接受任何非数字键
  if (".0123456789".includes(event.key)) {
    scoreStr += event.key;
  }
}
onMounted(() => {
  document.addEventListener("keydown", numberKeyListener);
});
onUnmounted(() => {
  document.removeEventListener("keydown", numberKeyListener);
});

const scrollToQuestion = (question: Question) => {
  const node = document.querySelector(
    `#q-${question.mainNumber}-${question.subNumber}`
  );
  node && node.scrollIntoView({ behavior: "smooth" });
};

watch(
  () => store.currentQuestion,
  () => {
    store.currentQuestion && scrollToQuestion(store.currentQuestion);
  }
);

function submit() {
  emit("submit");
}

const buttonHeightForSelective = $computed(() =>
  store.setting.selective && store.setting.enableAllZero ? "36px" : "76px"
);
</script>

<style scoped>
.mark-board-track-container {
  max-width: 290px;
  min-width: 290px;
  padding: 20px;
  max-height: calc(100vh - 56px - 0px);
  overflow: auto;
  z-index: 1001;
  transition: margin-right 0.5s;
  color: var(--app-small-header-text-color);
}
.mark-board-track-container.show {
  margin-right: 0;
}
.mark-board-track-container.hide {
  margin-right: -290px;
}

.top-container {
  background-color: var(--app-container-bg-color);
}
.total-score {
  color: var(--app-main-text-color);
  font-size: 32px;
}
.question {
  min-width: 80px;
  padding: 10px;
  background-color: var(--app-container-bg-color);
}
.current-question {
  color: white;
  background-color: var(--app-score-color);
}

.current-score {
  background-color: var(--app-score-color);
  color: white;
}
.all-zero-unselective-button {
  height: v-bind(buttonHeightForSelective);
  border-radius: 10px;
  padding: 7px;
  background-color: #4db9ff;
  border: none;
}
</style>
