<template>
  <div
    v-if="store.currentTask"
    class="mark-board-track-container"
    :class="[store.setting.uiSetting['score.board.collapse'] ? 'hide' : 'show']"
  >
    <div class="tw-my-2 tw-flex">
      <a-dropdown class="tw-self-end">
        <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="
        tw-flex tw-rounded tw-justify-between tw-p-2 tw-pl-5
        top-container
        tw-mb-4
      "
    >
      <div class="tw-flex tw-flex-col">
        <div class="tw-flex tw-items-center tw-gap-2">
          <img
            src="./images/totalscore.png"
            style="width: 13px; height: 16px"
          />
          总分
        </div>
        <div class="total-score tw-ml-5 tw-font-bold">
          {{ store.currentTask?.markResult.markerScore }}
        </div>
      </div>

      <div class="tw-flex tw-place-content-center tw-items-center tw-gap-2">
        <div class="tw-flex tw-flex-col tw-gap-1">
          <a-popconfirm
            v-if="store.setting.enableAllZero"
            title="确定给全零分？"
            ok-text="确定"
            cancel-text="取消"
            @confirm="$emit('allZeroSubmit')"
            :overlayStyle="{ width: '200px' }"
          >
            <a-button
              type="primary"
              size="middle"
              class="all-zero-unselective-button"
            >
              <span>全零分</span>
            </a-button>
          </a-popconfirm>
          <a-popconfirm
            v-if="store.setting.selective"
            title="确定是未选做？"
            ok-text="确定"
            cancel-text="取消"
            @confirm="$emit('unselectiveSubmit')"
            :overlayStyle="{ width: '200px' }"
          >
            <a-button
              type="primary"
              size="middle"
              class="all-zero-unselective-button"
            >
              <span>未选做</span>
            </a-button>
          </a-popconfirm>
        </div>

        <qm-button
          type="primary"
          shape="round"
          size="middle"
          style="height: 76px; border-radius: 10px; padding: 12px"
          @click="submit"
        >
          提交
        </qm-button>
      </div>
    </div>

    <div v-if="store.currentTask && store.currentTask.questionList">
      <template
        v-for="(question, index) in store.currentTask?.questionList"
        :key="index"
      >
        <div
          @click="
            () => {
              chooseQuestion(question);
              scrollToQuestion(question);
            }
          "
          class="
            question
            tw-rounded tw-p-1 tw-mb-2 tw-cursor-pointer tw-relative
          "
          :class="isCurrentQuestion(question) && 'current-question'"
          :id="'bq-' + question.mainNumber + '-' + question.subNumber"
        >
          <div
            v-if="isCurrentQuestion(question)"
            class="current-score-indicator"
          ></div>
          <div class="tw-flex tw-justify-between">
            <div>
              <div>
                {{ question.title }} {{ question.mainNumber }}-{{
                  question.subNumber
                }}
              </div>
              <div
                class="tw-text-center tw-text-3xl"
                :class="isCurrentQuestion(question) && 'current-score'"
              >
                {{
                  isCurrentQuestion(question)
                    ? scoreStr
                    : store.currentTask.markResult.scoreList[index]
                }}
              </div>
            </div>
            <div>
              <div class="tw-text-center">
                间隔{{ question.intervalScore }}分
              </div>
              <div class="tw-flex tw-text-3xl" style="width: 80px">
                <span class="tw-flex-1">{{ question.minScore }}</span>
                <span class="tw-flex-1">~</span>
                <span class="tw-flex-1 tw-text-center">{{
                  question.maxScore
                }}</span>
              </div>
            </div>
          </div>
        </div>
      </template>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { Question } from "@/types";
import { isNumber } from "lodash";
import { computed, 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 }
);

let 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
  );
}

let 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.currentTask?.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) {
      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)
      )
    ) {
      message.error({ content: "分数格式不正确", duration: 5 });
      console.log("分数格式不正确");
      return;
    }
    const score = parseFloat(scoreStr);
    // console.log(score);
    if (!isNumber(score)) {
      message.error({ content: "非数字输入", duration: 5 });
      console.log("非数字输入");
      return;
    }
    if (!questionScoreSteps.includes(score)) {
      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() as number;
    if (idx + 1 < store.currentTask.questionList.length) {
      chooseQuestion(store.currentTask.questionList[idx + 1]);
    }
    return;
  }
  if (event.key === "ArrowLeft") {
    const idx = indexOfCurrentQuestion() as number;
    if (idx > 0) {
      chooseQuestion(store.currentTask.questionList[idx - 1]);
    }
    event.preventDefault();
    return;
  }
  if (event.key === "ArrowRight") {
    const idx = indexOfCurrentQuestion() as number;
    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 handleMouseOverWithBoard = () => {
  if (store.setting.uiSetting["score.board.collapse"]) {
    const container = document.querySelector(".mark-board-track-container");
    if (container) {
      container.classList.add("show-board");
    }
  }
};

const handleMouseOutWithBoard = () => {
  if (store.setting.uiSetting["score.board.collapse"]) {
    const container = document.querySelector(".mark-board-track-container");
    if (container) {
      container.classList.remove("show-board");
    }
  }
};

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() {
  if (!store.currentTask) return;
  const errors: any = [];
  store.currentTask.markResult.scoreList.forEach((s, index) => {
    if (!isNumber(s) && store.currentTask) {
      const question = store.currentTask.questionList[index];
      errors.push({
        question,
        index,
        error: `${question.mainNumber}-${question.subNumber} 没有赋分不能提交。`,
      });
    }
  });
  if (errors.length === 0) {
    emit("submit");
  } else {
    console.log(errors);
    message.error({
      content: errors.map((e: any) => `${e.error}`).join("\n"),
      duration: 10,
    });
  }
}

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 .score {
  color: var(--high-light-score-color);
}

.current-score {
  color: var(--app-score-color);
}
.current-score-indicator {
  position: absolute;
  top: 0;
  left: 0;
  width: 5px;
  height: 5px;
  background-color: #5c69f6;
}
.all-zero-unselective-button {
  height: v-bind(buttonHeightForSelective);
  border-radius: 10px;
  padding: 7px;
  background-color: #4db9ff;
  border: none;
}
</style>
