<template>
  <el-dialog
    class="preview-paper-dialog"
    :visible.sync="visible"
    title="查看原卷"
    top="0"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    append-to-body
    fullscreen
    destroy-on-close
    @open="visibleChange"
  >
    <div ref="PaperBody" class="paper-body">
      <div
        v-if="renderStructList.length"
        class="paper-content paper-content-long"
      >
        <cont-item
          v-for="(item, index) in renderStructList"
          :key="index"
          :data="item"
        ></cont-item>
      </div>

      <div
        v-for="(group, gindex) in renderGroupStructList"
        :key="gindex"
        class="paper-content"
      >
        <cont-item
          v-for="(item, index) in group"
          :key="index"
          :data="item"
        ></cont-item>
      </div>
    </div>

    <div slot="footer"></div>
  </el-dialog>
</template>

<script>
import { studentExamDetailInfo } from "@/api/examwork-student";
import { numberToChinese, numberToUpperCase } from "./spins/renderJSON";
import ContItem from "./spins/ContItem.vue";
import previewTem from "./spins/previewTem";
import { randomCode } from "@/utils/utils";
import { STRUCT_TYPES } from "./spins/paperSetting";

export default {
  name: "preview-paper-dialog",
  components: { ContItem },
  props: {
    examRecordId: {
      type: String,
    },
  },
  data() {
    return {
      visible: false,
      paperStruct: {},
      renderStructList: [],
      renderGroupStructList: [],
    };
  },
  methods: {
    visibleChange() {
      this.paperStruct = {};
      this.renderStructList = [];
      this.renderGroupStructList = [];
      this.getRecordDetail();
    },
    openDialog() {
      this.visible = true;
    },
    closeDialog() {
      this.visible = false;
    },
    async getRecordDetail() {
      const res = await studentExamDetailInfo(this.examRecordId);
      this.parsePaperStruct(res.data.data);
      this.parseRenderStructList();

      const loadres = await this.waitAllImgLoaded().catch(() => {});
      if (!loadres) {
        this.$message.error("图片加载有误！");
        return;
      }
      this.$nextTick(() => {
        this.buildRenderGroupStructList();
      });
    },
    parsePaperStruct(data) {
      const paperStructJson = JSON.parse(data.paperStructJson);
      const answerJson = JSON.parse(data.answerJson);
      const examStudentAnswerJson = data.examStudentAnswerJson
        ? JSON.parse(data.examStudentAnswerJson)
        : [];
      // console.log(paperStructJson);
      // console.log(answerJson);
      // console.log(examStudentAnswerJson);

      const answerMap = {};
      answerJson.details.forEach((detail) => {
        detail.questions.forEach((question) => {
          const k = `${detail.number}-${question.number}`;
          if (question.subQuestions) {
            question.subQuestions.forEach((sq) => {
              answerMap[`${k}-${sq.number}`] = sq.answer;
            });
          } else {
            answerMap[k] = question.answer;
          }
        });
      });

      const studentAnsMap = {};
      examStudentAnswerJson.forEach((question) => {
        const k = `${question.mainNumber}-${question.subNumber}`;
        if (question.subQuestions) {
          question.subQuestions.forEach((sq) => {
            studentAnsMap[`${k}-${sq.number}`] = {
              answer: JSON.parse(sq.answer),
              score: sq.score,
            };
          });
        } else {
          studentAnsMap[k] = {
            answer: JSON.parse(question.answer),
            score: question.score,
          };
        }
      });

      // detail
      paperStructJson.details.forEach((detail) => {
        detail.questions.forEach((question) => {
          let k = `${detail.number}-${question.number}`;
          if (question.subQuestions) {
            question.subQuestions.forEach((sq) => {
              k += `-${sq.number}`;
              sq.answer = answerMap[k];
              const stdAns = studentAnsMap[k] || { answer: null, score: null };
              sq.studentAnswer = stdAns.answer;
              sq.studentScore = stdAns.score;
            });
          } else {
            question.answer = answerMap[k];
            const stdAns = studentAnsMap[k] || { answer: null, score: null };
            question.studentAnswer = stdAns.answer;
            question.studentScore = stdAns.score;
          }
        });
      });
      // console.log(JSON.stringify(paperStructJson));
      this.paperStruct = paperStructJson;
    },
    parseRenderStructList() {
      let renderStructList = [];
      renderStructList.push({
        cls: "paper-name",
        type: "text",
        content: this.paperStruct.name,
      });
      this.paperStruct.details.forEach((detail) => {
        renderStructList.push({
          cls: "detail-name",
          type: "text",
          content: `${numberToChinese(detail.number)}、${detail.name}`,
        });

        detail.questions.forEach((question) => {
          if (question.subQuestions) {
            if (question.body) {
              renderStructList.push({
                cls: "topic-title",
                type: "json",
                content: {
                  isCommon: true,
                  number: question.number,
                  body: question.body,
                },
              });
            }
            question.subQuestions.forEach((sq) => {
              const contents = this.parseSimpleQuestion(sq, false);
              renderStructList.push(...contents);
            });
          } else {
            const contents = this.parseSimpleQuestion(question, true);
            renderStructList.push(...contents);
          }
        });
      });

      this.renderStructList = renderStructList.map((item) => {
        item.id = randomCode();
        return item;
      });
      // console.log(renderStructList);
    },
    parseSimpleQuestion(question, isCommon) {
      let contents = [];
      contents.push({
        cls: "topic-title",
        type: "json",
        content: {
          isSub: !isCommon,
          number: question.number,
          body: question.body,
        },
      });

      if (question.options && question.options.length) {
        question.options.forEach((op) => {
          contents.push({
            cls: "topic-option",
            type: "json",
            content: {
              isSub: false,
              number: numberToUpperCase(op.number),
              body: op.body,
            },
          });
        });
      }

      if (question.answer) {
        contents.push({
          cls: "topic-answer",
          type: "json",
          content: {
            answerType: "standard",
            structType: question.structType,
            body: question.answer,
          },
        });
      }

      if (question.studentAnswer) {
        // 简答题的特殊处理，解决上传的大图无法分页问题。文字内容不受影响。
        if (question.structType === STRUCT_TYPES.TEXT) {
          // console.log(question.studentAnswer);
          let aindex = 0;
          question.studentAnswer.forEach((answer) => {
            answer.sections.forEach((section) => {
              contents.push({
                cls: "topic-answer std-answer",
                type: "json",
                content: {
                  answerType: "student",
                  structType: question.structType,
                  hideTitle: aindex !== 0,
                  body: [
                    {
                      sections: [section],
                    },
                  ],
                },
              });
              aindex++;
            });
          });
        } else {
          contents.push({
            cls: "topic-answer std-answer",
            type: "json",
            content: {
              answerType: "student",
              structType: question.structType,
              body: question.studentAnswer,
            },
          });
        }
      }

      contents.push({
        cls: "topic-score",
        type: "text",
        content: "得分：" + (question.studentScore || 0),
      });

      return contents;
    },
    loadImg(url) {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = function () {
          resolve(true);
        };
        img.onerror = function () {
          reject();
        };
        img.src = url;
      });
    },
    getRichJsonImgUrls(richJson) {
      let urls = [];
      richJson.sections.forEach((section) => {
        section.blocks.forEach((elem) => {
          if (elem.type === "image") {
            urls.push(elem.value);
          }
        });
      });
      return urls;
    },
    async waitAllImgLoaded() {
      let imgUrls = [];
      this.renderStructList.forEach((item) => {
        if (item.type === "text") return;
        if (item.cls === "topic-title" || item.cls === "topic-option") {
          imgUrls.push(...this.getRichJsonImgUrls(item.content.body));
          return;
        }
        // 简答题才可能会有图片
        if (item.cls.indexOf("answer") && item.content.structType === 5) {
          item.content.body.forEach((body) => {
            imgUrls.push(...this.getRichJsonImgUrls(body));
          });
        }
      });

      // console.log(imgUrls);

      if (!imgUrls.length) return Promise.resolve(true);
      const imgLoads = imgUrls.map((item) => this.loadImg(item));
      const imgLoadResult = await Promise.all(imgLoads).catch(() => {});
      if (imgLoadResult && imgLoadResult.length) {
        return Promise.resolve(true);
      } else {
        return Promise.reject();
      }
    },
    buildRenderGroupStructList() {
      const pageMaxHeight = 1042;
      let curGroup = [],
        curGroupHeight = 0;
      let renderGroupStructList = [];
      this.renderStructList.forEach((item) => {
        const itemHeight = document.getElementById(item.id).clientHeight;
        if (curGroupHeight + itemHeight > pageMaxHeight) {
          if (curGroup.length) renderGroupStructList.push(curGroup);
          curGroup = [];
          curGroupHeight = 0;
        }
        curGroup.push(item);
        curGroupHeight += itemHeight;
      });

      if (curGroup.length) renderGroupStructList.push(curGroup);

      this.renderGroupStructList = renderGroupStructList;
      this.renderStructList = [];
    },
    getPreviewHtml() {
      const html = previewTem(this.$refs.PaperBody.innerHTML);
      console.log(html);
    },
  },
};
</script>

<style src="@/styles/paper-preview.css"></style>
