<template>
  <el-dialog
    class="card-build-dialog opacity-dialog"
    :visible.sync="modalIsShow"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :show-close="false"
    append-to-body
    fullscreen
    @opened="initData"
  >
    <div slot="title"></div>
    <div slot="footer"></div>
    <div
      class="loading-tips"
      v-loading="loading"
      element-loading-text="生成题卡中"
    ></div>

    <div
      v-if="modalIsShow"
      id="card-build"
      class="card-build card-preview card-print"
    >
      <card-view
        v-if="pages.length"
        ref="CardView"
        class="preview-body"
        :pages="pages"
        :card-config="cardConfig"
      ></card-view>
      <!-- all topics -->
      <div v-else class="topic-list">
        <div :class="['page-box', `page-box-${cardConfig.pageSize}`]">
          <div class="page-main-inner">
            <div
              :class="['page-main', `page-main-${cardConfig.columnNumber}`]"
              :style="{ margin: `0 -${cardConfig.columnGap / 2}px` }"
            >
              <div
                class="page-column"
                :style="{ padding: `0 ${cardConfig.columnGap / 2}px` }"
              >
                <div class="page-column-main" id="topic-column">
                  <div class="page-column-body">
                    <!-- card-head-sample -->
                    <card-head-sample
                      :data="cardHeadSampleData"
                      id="simple-card-head"
                      v-if="topics.length && cardHeadSampleData"
                    ></card-head-sample>
                    <!-- topic element -->
                    <topic-element-preview
                      class="page-column-element"
                      v-for="element in topics"
                      :key="element.id"
                      :data="element"
                    ></topic-element-preview>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script>
import json5 from "json5";
import { mapState, mapMutations, mapActions } from "vuex";
import { saveCard, cardConfigInfos } from "../api";
import { tikuPaperDetail } from "../../exam/api";
import { getPaperJsonSimpleStructInfo } from "../autoBuild/paperStruct";
import { buildCardFromPaperSimpleStruct } from "../autoBuild/simplePaperCard";
// card components
import { getCardHeadModel } from "../../../../card/elementModel";
import TopicElementPreview from "../../../../card/components/TopicElementPreview";
import CardView from "../../../../card/components/CardView.vue";
import CardHeadSample from "../../../../card/elements/card-head/CardHead";
import { deepCopy, objTypeOf } from "@/plugins/utils";
// ceshi
// import paperData from "./paper.json";

export default {
  name: "CardBuild",
  components: { CardView, TopicElementPreview, CardHeadSample },
  props: {
    presetData: {
      type: Object,
      default() {
        return {
          paperId: "",
        };
      },
    },
  },
  data() {
    return {
      cardId: "",
      loading: false,
      modalIsShow: false,
      paperInfo: {},
      answers: {},
      cachePages: [],
      sysCardSize: "",
    };
  },
  computed: {
    ...mapState("card", ["cardConfig", "topics", "pages"]),
    cardHeadSampleData() {
      if (!this.cardConfig["pageSize"]) return;
      const data = getCardHeadModel(this.cardConfig);
      data.isSimple = true;
      return data;
    },
  },
  methods: {
    ...mapMutations("card", [
      "setCardConfig",
      "setTopics",
      "setPages",
      "initState",
    ]),
    ...mapActions("card", ["resetTopicSeries", "rebuildPages"]),
    async initData() {
      this.loading = true;
      this.sysCardSize = this.$ls.get("schoolInfo", {
        cardSize: this.sysCardSize,
      }).cardSize;

      this.initState();

      // 题卡规则
      const cardConfig = await this.getCardConfig(
        this.presetData.cardRuleId
      ).catch(() => {});
      if (!cardConfig) {
        this.emitResult({ success: false, message: "题卡规则获取失败" });
        return;
      }
      this.setCardConfig(cardConfig);

      // 试卷信息
      const res = await tikuPaperDetail({
        examId: this.presetData.examId,
        paperId: this.presetData.paperId,
        uuid: this.presetData.uuid,
      }).catch(() => {});
      if (!res) {
        this.emitResult({ success: false, message: "试卷内容获取失败" });
        return;
      }
      // const res = paperData;
      // 构建题卡
      try {
        this.paperInfo = {
          uuid: this.presetData.uuid,
          attachmentId: res.attachmentId,
          paperUrl: res.paperUrl,
        };
        const answerJson = res.answerJson
          ? json5.parse(res.answerJson)
          : { details: [] };
        const paperJson = res.paperJson
          ? json5.parse(res.paperJson)
          : { details: [] };

        this.rebuildPaperQuestionNumber(answerJson);
        this.rebuildPaperQuestionNumber(paperJson);
        this.parsePaperAnswers(paperJson, answerJson);

        const paperSimpleStruct = getPaperJsonSimpleStructInfo(paperJson);
        const elementTypePreSetInfo = {
          FILL_QUESTION: {
            pageSize: this.sysCardSize,
            columnNumber: 2,
          },
        };
        const elements = buildCardFromPaperSimpleStruct(
          paperSimpleStruct,
          elementTypePreSetInfo
        );
        this.setTopics([getCardHeadModel(this.cardConfig), ...elements]);
        this.resetTopicSeries();
      } catch (error) {
        console.dir(error);
        this.emitResult({
          success: false,
          message: error.message || "数据构建错误",
        });
        return;
      }

      this.$nextTick(() => {
        this.rebuildPages();
        this.cachePages = deepCopy(this.pages);
        // console.log(this.cachePages);
        this.updatePageField();

        this.$nextTick(() => {
          this.buildData();
        });
      });
    },
    rebuildPaperQuestionNumber(paperJson) {
      // 如果一个大题有多个套题，那么套题的小题需要将强制转成为小题号连续
      paperJson.details.forEach((detail) => {
        let qno = 1;
        detail.questions.forEach((question) => {
          if (question.subQuestions && question.subQuestions.length) {
            question.subQuestions.forEach((subq) => {
              subq.number = qno++;
            });
          } else {
            question.number = qno++;
          }
        });
      });
    },
    getObjectiveQuestionAnswer(answer) {
      if (objTypeOf(answer) === "boolean") {
        return answer ? "A" : "B";
      }
      if (objTypeOf(answer) === "array") {
        const abc = "abcdefghijklmnopqrstuvwxyz".toUpperCase();
        return answer.map((item) => abc[item - 1]).join();
      }
    },
    parsePaperAnswers(paperJson, answerJson) {
      const infos = {};
      const objectiveQuestionTypes = [1, 2, 3];
      paperJson.details.forEach((detail) => {
        detail.questions.forEach((question) => {
          if (question.subQuestions && question.subQuestions.length) {
            question.subQuestions.forEach((subq) => {
              const qno = `${detail.number}-${subq.number}`;
              if (!infos[qno]) {
                infos[qno] = {
                  answer: null,
                  score: null,
                  objective: false,
                };
              }
              infos[qno].score = subq.score;
              infos[qno].objective = objectiveQuestionTypes.includes(
                subq.structType
              );
            });
          } else {
            const qno = `${detail.number}-${question.number}`;
            if (!infos[qno]) {
              infos[qno] = { answer: null, score: null, objective: false };
            }
            infos[qno].score = question.score;
            infos[qno].objective = objectiveQuestionTypes.includes(
              question.structType
            );
          }
        });
      });
      answerJson.details.forEach((detail) => {
        detail.questions.forEach((question) => {
          if (question.subQuestions && question.subQuestions.length) {
            question.subQuestions.forEach((subq) => {
              const qno = `${detail.number}-${subq.number}`;
              if (infos[qno].objective) {
                infos[qno].answer = this.getObjectiveQuestionAnswer(
                  subq.answer
                );
              }
            });
          } else {
            const qno = `${detail.number}-${question.number}`;
            if (infos[qno].objective) {
              infos[qno].answer = this.getObjectiveQuestionAnswer(
                question.answer
              );
            }
          }
        });
      });

      this.answers = infos;
    },
    async getCardConfig(cardRuleId) {
      const data = await cardConfigInfos(cardRuleId);
      if (!data) {
        this.$message.error("找不到题卡规则！");
        return Promise.reject();
      }
      let config = {
        ...data,
        ...{
          pageSize: this.sysCardSize,
          columnNumber: 2,
          columnGap: 20,
          showForbidArea: false,
          makeMethod: "SELF",
          courseCodeBarcodeSrc: "${courseCodeBarcodeSrc}",
          courseCodeBarcodeName: "${courseCodeBarcodeName}",
        },
      };
      config.fillNumber = data.examNumberDigit;
      config.aOrB = false;
      config.requiredFields = JSON.parse(config.requiredFields);
      config.extendFields = JSON.parse(config.extendFields);
      config.relationList = JSON.parse(config.relationList || "[]");
      config.cardTitle = this.getCardTitle(config.titleRule);
      config.firstLevelSubheading = this.getCardTitle(
        config.firstLevelSubheading
      );
      config.secondLevelSubheading = this.getCardTitle(
        config.secondLevelSubheading
      );
      return config;
    },
    getCardTitle(titleRule) {
      const fieldMap = {
        courseCode: this.presetData.courseCode,
        courseName: this.presetData.courseName,
        schoolName: this.presetData.schoolName,
      };
      Object.entries(fieldMap).forEach(([key, val]) => {
        titleRule = titleRule.replace("${" + key + "}", val);
      });
      return titleRule;
    },
    updatePageField() {
      const config = this.cardConfig;
      // 变量
      let fieldInfos = {};
      [...config.requiredFields, ...config.extendFields]
        .filter((item) => item.enable)
        .map((item) => {
          fieldInfos[item.code] = "${" + item.code + "}";
        });

      const isPrintExamNumber = config.examNumberStyle === "PRINT";
      if (isPrintExamNumber) {
        fieldInfos.examNumber = "data:image/png;base64,${examNumber}";
        fieldInfos.examNumberStr = "${examNumberStr}";
      }
      if (config.aOrB && config.paperType === "PRINT") {
        fieldInfos.paperType = "data:image/png;base64,${paperType}";
        fieldInfos.paperTypeName = "${paperTypeName}";
      }

      const pages = this.pages.map((page, pageNo) => {
        if (pageNo % 2) return page;
        const cardHeadElement = page.columns[0].elements[0];

        if (cardHeadElement.type === "CARD_HEAD") {
          cardHeadElement.fieldInfos = fieldInfos;
        }
        return page;
      });
      this.setPages(pages);
    },
    async buildData() {
      const model = this.$refs.CardView.getPageModel({
        cardConfig: this.cardConfig,
        pages: this.cachePages,
        answers: this.answers,
      });
      const htmlContent = this.$refs.CardView.getPreviewTemp(
        document.getElementById("card-build").outerHTML
      );

      const datas = {
        content: model,
        htmlContent,
        title: this.presetData.paperName,
        status: "SUBMIT",
        pageSize: this.cardConfig.pageSize,
        openAb: this.cardConfig.aOrB,
        ...this.presetData,
      };
      const result = await saveCard(datas).catch((error) => {
        this.emitResult({
          success: false,
          message: error.message || "保存题卡错误",
        });
      });
      if (!result) return;
      this.emitResult({
        success: true,
        data: { ...result, ...this.paperInfo },
      });
    },
    emitResult(data) {
      // console.log(data);
      this.initState();
      this.loading = false;
      this.$emit("confirm", data);
      this.cancel();
    },
    cancel() {
      this.modalIsShow = false;
    },
    open() {
      this.modalIsShow = true;
    },
  },
};
</script>
