<template>
  <div class="exam-container">
    <header class="header">
      <div class="title">{{ examInfo.name }}</div>
      <div class="right">
        <div class="count" v-if="pageOptions.hasTime">{{ examTime }}</div>
        <!-- <div class="time">
            <div class="icon"></div>
            <div class="mun">60:00</div>
          </div> -->
      </div>
    </header>
    <div class="exam-main">
      <div class="left scroll" ref="questionRef">
        <QuestionList :paper="paper" :questionItems="questionItems" :questionNumber="questionNumber" @changeNumber="changeNumber" v-if="questionItems.length"></QuestionList>
      </div>
      <div class="right scroll">
        <QuestionNum :questionItems="questionItems" :questionNumber="questionNumber" :student="studentInfo" @changeNumber="changeNumber"></QuestionNum>
      </div>
    </div>
    <footer class="footer">
      <div class="exam-btn">
        <el-button :type="hasPrev ? 'primary' : 'default'" :disabled="!hasPrev" @click="handlePrev">上一题</el-button>
        <el-button :type="hasNext ? 'primary' : 'default'" :disabled="!hasNext" @click="handleNext">下一题</el-button>
      </div>
      <div class="right-btn">
        <div class="sign" @click="handleMark" v-if="pageOptions.hasMark">
          <div class="icon" :class="{ active: isMark }"></div>
          <div class="txt">{{ isMark ? '取消标记' : '标记' }}</div>
        </div>
        <div class="end-exam-btn">
          <el-button type="primary" @click="handleSubmitExam" v-if="pageOptions.hasSubmit">提交试卷</el-button>
          <el-button type="primary" @click="handleSaveExam" v-if="pageOptions.hasSave">保存</el-button>
        </div>
      </div>
    </footer>
  </div>
</template>
<script>
import * as api from '@/api/base.js'
import QuestionList from '@/components/QuestionList.vue'
import QuestionNum from '@/components/QuestionNum.vue'
import { merge } from 'lodash-es'

export default {
  components: { QuestionList, QuestionNum },
  data() {
    return {
      paper: {},
      questionItems: [],
      questionNumber: 1,
      examTime: '00:00:00 倒计时',
      countdownTimer: null,
      cacheExamTimer: null
    }
  },
  computed: {
    studentInfo() {
      return this.$store.state.studentInfo || {}
    },
    examInfo() {
      return this.$store.state.examInfo || {}
    },
    examId() {
      return this.examInfo.exam_id
    },
    // 当前试题
    question() {
      for (const group of this.questionItems) {
        for (const item of group.question_list) {
          if (item.list && item.list.find(item => item.q_number === this.questionNumber)) return item
          if (item.q_number === this.questionNumber) return item
        }
      }
      return {}
    },
    // 是否标记
    isMark() {
      if (this.question.list) {
        return this.question.list[0]?.sign
      }
      return this.question.sign
    },
    // 是否可以上一题
    hasPrev() {
      return this.questionNumber > 1
    },
    // 是否可以下一题
    hasNext() {
      return this.questionNumber < this.paper.total_question_count
    },
    pageOptions() {
      const { has_time = '1', has_mark = '1', has_submit = '1', has_save = '0' } = this.$route.query
      return {
        hasTime: has_time != '0',
        hasMark: has_mark != '0',
        hasSubmit: has_submit != '0',
        hasSave: has_save != '0'
      }
    }
  },
  mounted() {
    this.fetchExam()
  },
  beforeDestroy() {
    this.countdownTimer && clearInterval(this.countdownTimer)
    this.cacheExamTimer && clearInterval(this.cacheExamTimer)
  },
  methods: {
    // 获取试卷
    async fetchExam() {
      this.pageOptions.hasTime && this.setCountdownTimer()
      try {
        const res = await api.getTopic(this.examId)
        this.paper = res
        this.questionItems = this.genQuestionList(res.question_items)
        this.setCacheExamTimer()
        this.fetchExamCache()
      } catch (error) {
        this.$router.replace({ name: 'login', params: { examId: this.examId }, query: this.$route.query })
      }
    },
    // 获取缓存试卷
    async fetchExamCache() {
      const res = await api.getCache(this.examId)
      const data = JSON.parse(res.answer)
      if (data !== null && data !== 'null') {
        this.questionItems = this.genQuestionList(this.paper.question_items, data)
      }
    },
    // 组装试题数据
    genQuestionList(questions = [], answers = {}) {
      let qNumber = 0
      return questions.map(group => {
        const groupAnswers = answers?.[group.question_item_type]
        const baseAttrs = {
          question_item_id: group.question_item_id,
          question_item_title: group.question_item_title,
          question_item_type: group.question_item_type
        }
        const question_list = group.question_list.map(item => {
          if (item.list) {
            const list = item.list.map(item => {
              qNumber++
              const questionAnswers = groupAnswers?.[item.id]
              return { ...baseAttrs, ...item, sign: questionAnswers?.sign || false, answer: questionAnswers?.answer || [], q_number: qNumber }
            })
            return { ...baseAttrs, ...item, list }
          } else {
            qNumber++
            const questionAnswers = groupAnswers?.[item.id]
            return { ...baseAttrs, ...item, sign: questionAnswers?.sign || false, answer: questionAnswers?.answer || [], q_number: qNumber }
          }
        })
        return { ...group, question_list }
      })
    },
    // 获取答案
    getAnswer() {
      return this.questionItems.reduce((result, group) => {
        group.question_list.forEach(item => {
          if (item.list) {
            item.list.forEach(item => {
              const data = { [item.question_item_type]: { [item.id]: { answer: item.answer, sign: item.sign } } }
              result = merge(result, data)
            })
          } else {
            const data = { [item.question_item_type]: { [item.id]: { answer: item.answer, sign: item.sign } } }
            result = merge(result, data)
          }
        })
        return result
      }, {})
    },
    // 获取答题数量
    getAnswerCount() {
      let countNum = 0
      const answer = this.getAnswer()
      for (const item in answer) {
        const list = Object.values(answer[item])
        for (let i = 0; i < list.length; i++) {
          if (list[i].answer.length) countNum++
        }
      }
      return countNum
    },
    //  提交考试
    async handleSubmitExam() {
      const count = parseInt(this.paper.total_question_count) - parseInt(this.getAnswerCount())
      const confirmText =
        count === 0 ? '确定后要结束本次考试？还有作答时间，结束考试后，将不能返回本次考试！' : `确定要结束本次考试？还有${count}题未答，结束考试后，将不能返回本次考试`
      await this.$confirm(confirmText, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '关闭',
        type: 'warning'
      })
      await this.postExam()
      this.$router.replace({ name: 'examEnd', params: { examId: this.examId }, query: this.$route.query })
    },
    // 确认提交考试
    async postExam() {
      const params = { answer: JSON.stringify(this.getAnswer()) }
      this.cacheExamTimer && clearInterval(this.cacheExamTimer)
      await api.endExam(this.examId, params)
      this.$message.success('提交成功')
    },
    // 保存试卷
    async handleSaveExam() {
      await this.postCacheExam()
      this.$message.success('保存成功')
    },
    // 缓存试卷
    async postCacheExam() {
      const params = { answer: JSON.stringify(this.getAnswer()) }
      await api.setCache(this.examId, params)
    },
    // 自动缓存试卷
    setCacheExamTimer() {
      // 10 秒缓存一次试卷
      this.cacheExamTimer = setInterval(() => {
        this.postCacheExam()
      }, 10000)
    },
    // 倒计时
    setCountdownTimer() {
      this.countdownTimer = setInterval(() => {
        const nowTime = new Date()
        const endTime = new Date(this.examInfo.end_time.replace(/-/g, '/'))
        const countTime = endTime.getTime() - nowTime.getTime()
        if (countTime <= 0) {
          this.handleTimeout()
          this.examTime = '00:00:00 倒计时'
        } else {
          const leftTime = parseInt(countTime / 1000)
          const h = parseInt((leftTime / (60 * 60)) % 24)
            .toString()
            .padStart(2, '0')
          const m = parseInt((leftTime / 60) % 60)
            .toString()
            .padStart(2, '0')
          const s = parseInt(leftTime % 60)
            .toString()
            .padStart(2, '0')
          this.examTime = `${h} : ${m} : ${s} 倒计时`
        }
      }, 1000)
    },
    // 时间结束
    handleTimeout() {
      this.$alert('考试时间到', {
        confirmButtonText: '确定',
        callback: () => {
          this.$router.replace({ name: 'examEnd', params: { examId: this.examId }, query: this.$route.query })
        }
      })
      this.countdownTimer && clearInterval(this.countdownTimer)
      // 提交试卷
      this.postExam()
    },
    // 标记
    handleMark() {
      if (this.question.list) {
        this.question.list.forEach(item => {
          item.sign = !item.sign
        })
      } else {
        this.question.sign = !this.question.sign
      }
    },
    // 上一题
    handlePrev() {
      this.changeNumber(this.questionNumber - 1)
    },
    // 下一题
    handleNext() {
      this.changeNumber(this.questionNumber + 1)
    },
    changeNumber(number) {
      this.questionNumber = number
      this.$refs.questionRef.scrollTo(0, 0)
    }
  }
}
</script>
<style lang="scss" scoped>
.exam-container {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  .header {
    background: #fff;
    display: flex;
    .title {
      padding-left: 30px;
      font-size: 24px;
      font-weight: bold;
      color: #222222;
      line-height: 60px;
    }
    .right {
      position: relative;
      width: 260px;
      margin-left: auto;
      display: flex;
      justify-content: space-around;
      align-items: center;
      .count {
        font-size: 18px;
        font-weight: bold;
        color: #222222;
      }
      .time {
        display: flex;
        .icon {
          width: 23px;
          height: 23px;
          background: url(../assets/images/tick.png);
          background-size: 100% 100%;
        }
        .mun {
          font-size: 18px;
          font-weight: bold;
          color: #222222;
          line-height: 25px;
          margin-left: 10px;
        }
      }
    }
  }
  .exam-main {
    flex: 1;
    display: flex;
    overflow: hidden;

    .left {
      flex: 1;
      padding: 10px 30px;
      &.scroll {
        overflow-y: scroll;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        &::-webkit-scrollbar {
          display: none;
        }
      }
    }
    .right {
      position: relative;
      width: 220px;
      background: #fff;
      padding: 0 20px;
      &.scroll {
        overflow-y: scroll;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        &::-webkit-scrollbar {
          display: none;
        }
      }
    }
  }
  .footer {
    height: 60px;
    background: #ffffff;
    display: flex;
    align-items: center;
    .exam-btn {
      display: flex;
      padding-left: 30px;
      cursor: pointer;
      .el-button {
        width: 100px;
      }
    }
    .right-btn {
      display: flex;
      margin-left: auto;
      .end-exam-btn {
        width: 260px;
        display: flex;
        justify-content: center;
        align-items: center;
        .el-button {
          width: 200px;
        }
      }
      .sign {
        cursor: pointer;
        margin-right: 20px;
        .icon {
          margin: 0 auto;
          width: 24px;
          height: 24px;
          background: url(../assets/images/sign.png);
          background-size: 100% 100%;
          &.active {
            background: url(../assets/images/sign2.png);
            background-size: 100% 100%;
          }
        }
        .txt {
          font-size: 14px;
          color: #cccccc;
          line-height: 20px;
          margin-top: 2px;
        }
      }
    }
  }
}
</style>
