<template>
  <div class="list">
    <table>
      <tbody class="list-row">
        <tr class="list-header qm-primary-strong-text">
          <td>课程</td>
          <td v-if="!isEpcc" key="cc">层次</td>
          <td v-if="!isEpcc" key="zy">专业</td>
          <td>考试开放时间</td>
          <td>剩余考试次数</td>
          <td style="max-width: 200px">操作</td>
        </tr>

        <tr v-for="course in courses" :key="course.examId + course.courseId">
          <td>{{ course.courseName }}</td>
          <td v-if="!isEpcc" key="cc">{{ course.courseLevel }}</td>
          <td v-if="!isEpcc" key="zy">{{ course.specialtyName }}</td>
          <td>
            {{ course.startTime }} <br />
            ~ <br />
            {{ course.endTime }}
          </td>
          <td>{{ course.allowExamCount }}</td>
          <td style="min-width: 180px">
            <div
              style="display: grid; grid-template-columns: repeat( auto-fit, minmax(100px, 1fr) ); 
                        grid-gap: 10px"
            >
              <i-button
                class="qm-primary-button qm-primary-button-padding-fix"
                :disabled="disableTheCourse(course)"
                :title="disableTheCourse(course) ? disableReason(course) : ''"
                @click="
                  () => {
                    if (isEpcc) {
                      raceEnter(course);
                    } else {
                      enterExam(course);
                    }
                  }
                "
              >
                进入考试{{ isEpcc && countdown > 0 ? `(${countdown})` : "" }}
              </i-button>
              <i-poptip
                v-if="!isEpcc"
                :trigger="course.isObjScoreView ? 'hover' : 'click'"
                placement="left"
                class="online-exam-list-override-poptip"
                @on-popper-show="cid = course.courseId"
                @on-popper-hide="cid = null"
              >
                <i-button
                  class="qm-primary-button qm-primary-button-padding-fix"
                  style="width: 100%"
                  :disabled="!course.isObjScoreView"
                >
                  客观分
                </i-button>
                <ecs-online-exam-result-list
                  slot="content"
                  :popper-show="cid === course.courseId"
                  :exam-student-id="course.examStudentId"
                ></ecs-online-exam-result-list>
              </i-poptip>
            </div>
          </td>
        </tr>
      </tbody>
    </table>

    <Spin v-if="spinShow" size="large" fix>{{ processingMessage }}</Spin>
    <OnlineExamFaceCheckModal
      :open="faceCheckModalOpen"
      :course="selectedCourse"
    ></OnlineExamFaceCheckModal>

    <Modal
      ref="checkEnvModal"
      v-model="shouldShowCheckEnvModal"
      title="环境检测"
      footer-hide
      width="800"
      :closable="false"
      :mask-closable="false"
    >
      <CheckComputer
        v-if="shouldShowCheckEnvModal"
        @on-close="resumeEnterExam"
      />
    </Modal>
  </div>
</template>

<script>
import { createNamespacedHelpers } from "vuex";
import OnlineExamResultList from "./OnlineExamResultList.vue";
import OnlineExamFaceCheckModal from "./OnlineExamFaceCheckModal.vue";
import moment from "moment";
import {
  mapState as globalMapState,
  mapGetters as globalMapGetters,
} from "vuex";
const { mapState, mapMutations } = createNamespacedHelpers("examHomeModule");
import CheckComputer from "./CheckComputer";
import axios from "axios";

export default {
  name: "EcsOnlineList",
  components: {
    "ecs-online-exam-result-list": OnlineExamResultList,
    OnlineExamFaceCheckModal,
    CheckComputer,
  },
  props: {
    courses: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      now: new Date(),
      selectedCourse: null,
      spinShow: false,
      processingMessage: "",
      cid: null,
      shouldShowCheckEnvModal: false,
      countdown: 0,
    };
  },
  computed: {
    ...globalMapState(["user", "timeDifference"]),
    ...mapState(["faceCheckModalOpen"]),
    ...globalMapGetters(["isEpcc"]),
  },
  created() {
    this.getNow();
    this.intervalID = setInterval(() => this.getNow(), 1000);
  },
  beforeDestroy() {
    this.toggleFaceCheckModal(false);
    clearInterval(this.intervalID);
    clearInterval(this.countdownInterval);
  },
  methods: {
    ...mapMutations(["toggleFaceCheckModal"]),
    getNow() {
      this.now = Date.now() + this.timeDifference;
    },
    courseInBetween(course) {
      return moment(this.now).isBetween(
        moment(course.startTime),
        moment(course.endTime)
      );
    },
    disableReason(course) {
      if (!this.courseInBetween(course)) {
        return "当前时间不在考试开放时间范围";
      } else if (course.allowExamCount < 1) {
        return "无剩余考试次数";
      } else if (this.isEpcc && this.countdown > 0) {
        return "请稍后点击";
      } else {
        return "";
      }
    },
    disableTheCourse(course) {
      return (
        !this.courseInBetween(course) ||
        course.allowExamCount < 1 ||
        (this.isEpcc && this.countdown > 0)
      );
    },
    async raceEnter(course) {
      const minutesAfterCourseStart = Math.floor(
        moment(this.now).diff(moment(course.startTime), "seconds") / 30
      );

      window._hmt.push([
        "_trackEvent",
        "在线考试列表页面",
        "摇号进入考试-courseId-" + course.examId,
        minutesAfterCourseStart < 120
          ? minutesAfterCourseStart / 2 + "分进行点击"
          : "60分后进行点击",
      ]);

      let serverOk = false;
      let serverPass = false;
      try {
        const res = await axios.get(
          "https://rate-limit.qmth.com.cn/rateLimit",
          { timeout: 5 * 1000 }
        );
        serverOk = true;
        serverPass = res.data.pass;
      } catch (error) {
        console.log(error);
        window._hmt.push([
          "_trackEvent",
          "在线考试列表页面",
          "获取rateLimit失败",
        ]);
      }

      const successRatePerMinute = [0.5, 0.5, 0.5, 0.5, 1]; // 30秒步进

      let idx = 0;
      if (minutesAfterCourseStart < 0) {
        idx = 0;
      } else if (
        minutesAfterCourseStart >= 0 &&
        minutesAfterCourseStart < successRatePerMinute.length
      ) {
        idx = minutesAfterCourseStart;
      } else {
        idx = successRatePerMinute.length - 1;
      }
      if (
        (serverOk && serverPass) ||
        (!serverOk && Math.random() > 1 - successRatePerMinute[idx])
      ) {
        window._hmt.push([
          "_trackEvent",
          "在线考试列表页面",
          "摇号进入考试-courseId-" + course.examId,
          minutesAfterCourseStart < 120
            ? minutesAfterCourseStart / 2 + "分进入"
            : "60分后进入",
        ]);

        this.enterExam(course);
        // return true;
      } else {
        window._hmt.push([
          "_trackEvent",
          "在线考试列表页面",
          "摇号进入考试-courseId-" + course.examId,
          minutesAfterCourseStart < 120
            ? minutesAfterCourseStart / 2 + "分被限流"
            : "60分后被限流",
        ]);
        this.$Modal.warning({
          title: "提示",
          content: "考试人员过多，请稍等2分钟再试。",
          onOk: () => {
            clearInterval(this.countdownInterval);
            this.countdown = 10;
            this.countdownInterval = setInterval(() => {
              this.countdown--;
            }, 1 * 1000);
            // this.enterExam(course);
          },
        });
      }
    },
    async enterExam(course, alreadyChecked) {
      this.spinShow = true;
      this.processingMessage = "正在检测断点续考信息...";

      try {
        const alreadyInExam = await this.checkExamInProgress();
        if (alreadyInExam) {
          this.spinShow = false;
          this.logger({ action: "断点续考", detail: "在线考试列表页面" });
          window._hmt.push([
            "_trackEvent",
            "在线考试列表页面",
            "断点续考",
            "进入",
          ]);
          return;
        }
      } catch (error) {
        this.spinShow = false;
        return;
      }

      this.spinShow = true;
      this.processingMessage = "正在检测IP合法性...";
      try {
        const ipLimit = (await this.$http.get(
          "/api/ecs_exam_work/exam/ipLimit/" + course.examId
        )).data;
        // sleep function: await new Promise(resolve => setTimeout(() => resolve(), 3000));
        if (ipLimit.limited) {
          window._hmt.push(["_trackEvent", "在线考试列表页面", "IP受限"]);
          this.spinShow = false;
          this.$Message.error({
            content: "IP受限，请到中心指定地点进行考试！",
            duration: 15,
            closable: true,
          });
          return;
        }
      } catch (error) {
        this.$Message.error({
          content: "查询IP限制出错！",
          duration: 15,
          closable: true,
        });
        this.spinShow = false;
        return;
      }

      this.processingMessage = "正在获取考试设置...";

      if (!alreadyChecked) {
        let checkEnv = null;
        try {
          checkEnv = await this.$http.get(
            "/api/ecs_exam_work/exam/getExamPropertyFromCacheByStudentSession/" +
              course.examId +
              `/CHECK_ENVIRONMENT`
          );
          if (checkEnv.data.CHECK_ENVIRONMENT === "true") {
            const skipCheck = await new Promise(resolve => {
              this.$Modal.confirm({
                title: "进行环境检测",
                content:
                  "环境检测可以检测电脑的硬件配置、网络速度和常用操作。环境检测不通过的话，可能影响考试的正常进行。",
                okText: "进行检测",
                cancelText: "跳过检测",
                onOk: () => {
                  // sessionStorage.setItem(
                  //   "computer_env_ok_save_course_id",
                  //   course.courseId
                  // );
                  // this.$router.push("/check-computer");
                  // this.$refs.checkEnvModal.show();
                  this.shouldShowCheckEnvModal = true;
                  this.selectedCourse = course;
                  resolve();
                },
                onCancel: () => {
                  resolve(true);
                },
              });
            });
            if (!skipCheck) {
              this.spinShow = false;
              return;
            }
          }
        } catch (error) {
          this.spinShow = false;
          this.$Message.error({
            content: "查询考试的环境检测设置属性出错！",
            duration: 15,
            closable: true,
          });
          return;
        }
      }

      if (course.faceEnable) {
        // if 人脸检测 && 没有底照，提示，并返回
        if (!this.user.photoPath) {
          this.spinShow = false;
          window._hmt.push(["_trackEvent", "在线考试列表页面", "无底照"]);
          this.$Message.info(
            "本场考试需要进行人脸检测，但是您没有上传底照，请联系老师！"
          );
          return;
        }

        let faceLiveness = null;
        try {
          faceLiveness = await this.$http.get(
            "/api/ecs_exam_work/exam/identificationOfLivingEnabled/" +
              course.examId
          );
        } catch (error) {
          this.spinShow = false;
          this.$Message.error({
            content: "查询考试的人脸检测设置属性出错！",
            duration: 15,
            closable: true,
          });
          return;
        }
        if (faceLiveness.data) {
          this.processingMessage = "正在检测底照是否满足活体检测标准...";
          let checkBasePhoto;
          try {
            checkBasePhoto = (await this.$http.get(
              "/api/ecs_oe_student/examFaceLivenessVerify/checkFaceLiveness" +
                `?${this.user.token}` // 考生采用相同的机器考试，使用不同的请求的缓存
            )).data;
            this.spinShow = false;
            if (!checkBasePhoto.success) {
              this.$Message.error(
                "您上传的底照不符合活体检测的要求，请联系老师！"
              );
              window._hmt.push([
                "_trackEvent",
                "在线考试列表页面",
                "人脸识别框",
                "您上传的底照不符合活体检测的要求，请联系老师！",
              ]);
              return;
            }
          } catch (error) {
            this.spinShow = false;
            this.$Message.error({
              content: "查询检测底照是否满足活体检测标准的接口出错！",
              duration: 15,
              closable: true,
            });
            return;
          }
        }
        this.spinShow = false;
        // open face check modal, then
        // if 人脸识别失败 && 考试开启强制人脸识别 return
        // if 人脸识别失败 && 考试未开启强制人脸识别
        //    让学生手动确认进入考试，若取消，则返回
        this.selectedCourse = course;
        window._hmt.push([
          "_trackEvent",
          "在线考试列表页面",
          "人脸识别框",
          "弹出框",
        ]);
        this.toggleFaceCheckModal(true);
      } else {
        this.spinShow = false;
        this.logger({ action: "进入考试", detail: "无人脸检测" });
        window._hmt.push([
          "_trackEvent",
          "在线考试列表页面",
          "进入考试",
          "无人脸检测",
        ]);
        this.$router.push(
          `/online-exam/exam/${course.examId}/overview?examStudentId=${course.examStudentId}`
        );
      }
    },
    // eslint-disable-next-line
    async faceCheckResultCallback(course, faceMatched) {
      // if faceMatched
    },
    async resumeEnterExam() {
      this.shouldShowCheckEnvModal = false;
      this.enterExam(this.selectedCourse, true);
    },
  },
  // watch: {
  //   courses(value) {
  //     if (value.length > 0) {
  //       let courseId = sessionStorage.getItem("computer_env_ok_save_course_id");
  //       if (courseId !== null) {
  //         courseId = +courseId; // 转为数字
  //         const course = value.find(v => v.courseId === courseId);
  //         if (course) {
  //           this.enterExam(course, true);
  //           sessionStorage.removeItem("computer_env_ok_save_course_id");
  //         }
  //       }
  //     }
  //   },
  // },
};
</script>

<style scoped>
.list {
  border: 1px solid #eeeeee;
  border-radius: 6px;
}

.list table {
  width: 100%;
  border-collapse: collapse !important;
  border-spacing: 0;
}
.list td {
  border: 1px solid #eeeeee;
  border-radius: 6px;
  border-collapse: separate !important;
  padding: 10px;
}
</style>

<style>
.online-exam-list-override-poptip .ivu-poptip-rel {
  width: 100%;
}
</style>
