<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, MAX_WIDTH, MAX_HEIGHT } from "./spins/paperSetting";
const OPTION_NAME = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

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();
      });
    },
    checkIsMatches(structType) {
      const matchesTypes = [8, 9, 10];
      return matchesTypes.includes(structType);
    },
    parsePaperStruct(data) {
      const paperStructJson = data.paperStructJson
        ? JSON.parse(data.paperStructJson)
        : { details: [] };
      const answerJson = data.answerJson
        ? JSON.parse(data.answerJson)
        : { details: [] };
      const examStudentAnswerJson = data.examStudentAnswerJson
        ? JSON.parse(data.examStudentAnswerJson)
        : [];
      const subjectiveScoreDetailJson = data.subjectiveScoreDetailJson
        ? JSON.parse(data.subjectiveScoreDetailJson)
        : [];
      const randomPaperStructPath = data.randomPaperStructPath
        ? JSON.parse(data.randomPaperStructPath)
        : { details: [] };
      // console.log(JSON.stringify(randomPaperStructPath));
      // console.log(paperStructJson);
      // console.log(answerJson);
      // console.log(examStudentAnswerJson);

      const isEmpty = (cont) =>
        cont === undefined || cont === null || cont === "";

      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.subIndex !== null) {
          studentAnsMap[`${k}-${question.subIndex}`] = {
            answer: JSON.parse(question.answer),
            score: question.score,
          };
        } else {
          studentAnsMap[k] = {
            answer: JSON.parse(question.answer),
            score: question.score,
          };
        }
      });
      subjectiveScoreDetailJson.forEach((question) => {
        let k = `${question.mainNumber}-${question.subNumber}`;
        if (question.subIndex) {
          k = `${k}-${question.subIndex}`;
        }
        if (studentAnsMap[k]) {
          studentAnsMap[k].score = question.score;
        } else {
          studentAnsMap[k] = {
            score: question.score,
            answer: null,
          };
        }
      });

      // detail
      paperStructJson.details.forEach((detail) => {
        detail.questions.forEach((question) => {
          let k = `${detail.number}-${question.number}`;
          if (question.subQuestions) {
            const isMatches = this.checkIsMatches(question.structType);
            question.subQuestions.forEach((sq) => {
              if (isMatches) sq.options = [];
              const sqk = `${k}-${sq.number}`;
              sq.answer = isEmpty(answerMap[sqk]) ? null : answerMap[sqk];
              const stdAns = studentAnsMap[sqk] || {
                answer: null,
                score: null,
              };
              sq.studentAnswer = stdAns.answer;
              sq.studentScore = stdAns.score;
            });
          } else {
            question.answer = isEmpty(answerMap[k]) ? null : answerMap[k];
            const stdAns = studentAnsMap[k] || { answer: null, score: null };
            question.studentAnswer = stdAns.answer;
            question.studentScore = stdAns.score;
          }
        });
      });

      let studentPaperStructJson = { ...paperStructJson };
      if (randomPaperStructPath.details.length) {
        studentPaperStructJson.details = randomPaperStructPath.details.map(
          (detail, dindex) => {
            // const rDetail = { ...paperStructJson.details[detail.number - 1] };
            const rDetail = paperStructJson.details.find(
              (item) => item.number === detail.number
            );
            if (!rDetail) return;
            rDetail.number = dindex + 1;
            rDetail.questions = detail.questions.map((question, qindex) => {
              // 试题乱序
              const rQuestion = { ...rDetail.questions[question.number - 1] };
              rQuestion.number = qindex + 1;
              if (question.options) {
                // 选项乱序
                let optionMap = {};
                rQuestion.options = question.options.map((opNo, oindex) => {
                  const rOption = { ...rQuestion.options[opNo - 1] };
                  rOption.number = oindex + 1;
                  optionMap[opNo] = oindex + 1;
                  return rOption;
                });
                if (rQuestion.answer) {
                  rQuestion.answer = rQuestion.answer.map(
                    (ans) => optionMap[ans]
                  );
                }
                if (rQuestion.studentAnswer) {
                  rQuestion.studentAnswer = rQuestion.studentAnswer.map(
                    (ans) => optionMap[ans]
                  );
                }
              }
              return rQuestion;
            });
            return rDetail;
          }
        );
      }

      this.paperStruct = studentPaperStructJson;
    },
    transformRichJson(richJson) {
      if (!richJson || !richJson.sections) return [];
      let contents = [];
      let curBlock = [];
      const checkNeedSplitSection = (block) => {
        if (block.type !== "image") return false;

        if (block.param) {
          if (block.param.width) return block.param.width > MAX_WIDTH / 2;
          if (block.param.height) return block.param.height > 150;
        }
        return true;
      };

      richJson.sections.forEach((section) => {
        section.blocks.forEach((block) => {
          if (checkNeedSplitSection(block) && curBlock.length) {
            contents.push({ sections: [{ blocks: [...curBlock] }] });
            curBlock = [];
          }
          curBlock.push(block);
        });

        if (curBlock.length) {
          contents.push({ sections: [{ blocks: [...curBlock] }] });
          curBlock = [];
        }
      });
      return contents;
    },
    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}`,
        });
        const dbodys = this.parseTopicDesc(detail.description);
        renderStructList.push(...dbodys);

        detail.questions.forEach((question) => {
          if (question.subQuestions) {
            const bodys = this.parseTopicTitle(
              question.body,
              `${question.number}、`
            );
            renderStructList.push(...bodys);

            const isMatches = this.checkIsMatches(question.structType);
            if (isMatches && question.options && question.options.length) {
              question.options.forEach((op) => {
                const obodys = this.parseTopicOption(op.body, op.number);
                renderStructList.push(...obodys);
              });
            }

            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 = [];

      const tbodys = this.parseTopicTitle(
        question.body,
        isCommon ? `${question.number}、` : `${question.number}）`
      );
      contents.push(...tbodys);

      if (question.options && question.options.length) {
        question.options.forEach((op) => {
          const obodys = this.parseTopicOption(op.body, op.number);
          contents.push(...obodys);
        });
      }

      if (question.answer !== null) {
        // console.log(question.answer);
        const conts = this.parseTopicAnswer(
          question.answer,
          question.structType,
          false
        );
        contents.push(...conts);
      }

      if (question.studentAnswer !== null) {
        const conts = this.parseTopicAnswer(
          question.studentAnswer,
          question.structType,
          true
        );
        contents.push(...conts);
      }

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

      return contents;
    },
    parseTopicDesc(richJson) {
      if (!richJson) return [];
      const bodys = this.transformRichJson(richJson);
      return bodys.map((body) => {
        return {
          cls: "detail-desc",
          type: "json",
          content: body,
        };
      });
    },
    parseTopicTitle(richJson, numberVal) {
      if (!richJson) {
        return {
          cls: "topic-title",
          type: "json",
          content: {
            sections: [
              {
                blocks: [
                  {
                    type: "text",
                    value: numberVal,
                    param: { bold: true },
                  },
                ],
              },
            ],
          },
        };
      }

      const bodys = this.transformRichJson(richJson);

      return bodys.map((body, index) => {
        if (index === 0) {
          body.sections[0].blocks.unshift({
            type: "text",
            value: numberVal,
            param: { bold: true },
          });
        }
        return {
          cls: "topic-title",
          type: "json",
          content: body,
        };
      });
    },
    parseTopicOption(richJson, number) {
      const bodys = this.transformRichJson(richJson);

      return bodys.map((body, index) => {
        if (index === 0) {
          body.sections[0].blocks.unshift({
            type: "text",
            value: `${numberToUpperCase(number)}、`,
          });
        }
        return {
          cls: "topic-option",
          type: "json",
          content: body,
        };
      });
    },
    parseTopicAnswer(answer, structType, isStdAns) {
      // console.log(answer, structType, isStdAns);
      const answerTitleBlock = {
        type: "text",
        value: isStdAns ? "学生答案：" : "标准答案：",
        param: {
          bold: true,
        },
      };
      let contents = [];
      if (
        structType === STRUCT_TYPES.FILL_BLANK ||
        structType === STRUCT_TYPES.TEXT
      ) {
        contents.push({
          cls: "topic-answer",
          type: "json",
          content: {
            sections: [
              {
                blocks: [{ ...answerTitleBlock }],
              },
            ],
          },
        });
        answer.forEach((item) => {
          const bodys = this.transformRichJson(item);
          const conts = bodys.map((body, index) => {
            if (index === 0) {
              // body.sections[0].blocks.unshift({
              //   type: "text",
              //   value: "",
              // });
            }
            return {
              cls: "topic-answer",
              type: "json",
              content: body,
            };
          });
          contents.push(...conts);
        });
      } else {
        let ansCont = "";
        if (structType === STRUCT_TYPES.BOOLEAN_CHOICE) {
          ansCont = answer ? "对" : "错";
        } else {
          ansCont = answer.map((item) => OPTION_NAME[item - 1]).join("");
        }
        contents.push({
          cls: "topic-answer",
          type: "json",
          content: {
            sections: [
              {
                blocks: [
                  { ...answerTitleBlock },
                  { type: "text", value: ansCont },
                ],
              },
            ],
          },
        });
      }
      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 = [];
      if (!richJson) return 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;
        imgUrls.push(...this.getRichJsonImgUrls(item.content));
      });

      // 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() {
      let curGroup = [],
        curGroupHeight = 0;
      let renderGroupStructList = [];
      this.renderStructList.forEach((item) => {
        const itemHeight = document.getElementById(item.id).clientHeight;
        if (curGroupHeight + itemHeight > MAX_HEIGHT) {
          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>
