<template>
  <div class="remain-time">
    剩余时间
    <span
      :class="
        enhancedRemainTime && 'enhanced-remain-time animated infinite pulse'
      "
    >
      {{ remainTimeFormatted }}
    </span>
  </div>
</template>

<script>
import moment from "moment";
import { createNamespacedHelpers } from "vuex";
const { mapMutations } = createNamespacedHelpers("examingHomeModule");

export default {
  name: "RemainTime",
  data() {
    return {
      remainTime: null,
      enhancedRemainTime: true,
    };
  },
  computed: {
    remainTimeFormatted: function() {
      return this.remainTime
        ? moment.utc(this.remainTime).format("HH:mm:ss")
        : "计算中";
    },
  },
  watch: {
    remainTime(val) {
      if (val !== null && val === 0) {
        this.setShouldSubmitPaper();
      }
      this.updateRemainTime(val);
    },
  },
  async mounted() {
    this.heartbeatErrorNum = 0;
    this.getRemainTimeFromServer();
    this.heartbeatInterval = setInterval(() => {
      this.getRemainTimeFromServer();
    }, 60 * 1000);
    this.remainTimeInterval = setInterval(() => {
      if (this.remainTime > 0) {
        this.remainTime = this.remainTime - 1000;
      }
    }, 1000);

    this.__count = 10;
    this.enhancedRemainTimeInterval = setInterval(() => {
      if (this.__count-- <= 0) {
        this.enhancedRemainTime = false;
        clearInterval(this.enhancedRemainTimeInterval);
      }
    }, 1000);
  },
  beforeDestroy() {
    this.clearIntervals();
  },
  methods: {
    ...mapMutations(["setShouldSubmitPaper", "updateRemainTime"]),
    async getRemainTimeFromServer() {
      if (this.$route.name !== "OnlineExamingHome") {
        // 非考试页，不继续发心跳。可能退出后再进，导致心跳多发一次。可能会话已过期。
        return;
      }
      try {
        const res = await this.$http.get(
          "/api/ecs_oe_student/examControl/examHeartbeat"
        );
        this.logger({ action: "发出心跳", response: res.data });
        if (/\d+/.test(res.data)) {
          if (res.data <= 0) {
            this.setShouldSubmitPaper();
          }
          if (this.remainTime === null) {
            // 仅当剩余考试时间没有被初始化才使用服务器时间。否则使用本机时间。
            this.remainTime = res.data;
            console.log("初始化剩余时间");
          }
          this.heartbeatErrorNum = 0;
        } else {
          this.$Message.error({
            content: "服务器返回的心跳结果不是数字",
            duration: 15,
            closable: true,
          });
        }
      } catch (error) {
        if (
          error.response &&
          error.response.data &&
          error.response.data.desc &&
          error.response.data.desc.includes("会话已过期,请离开考试")
        ) {
          window._hmt.push([
            "_trackEvent",
            "正在考试页面",
            "心跳",
            "失败-会话过期",
          ]);
          this.logger({
            action: "发出心跳",
            error: "心跳失败",
            detail: "失败-会话过期",
          });
          this.serverLog(
            "debug/S-008002",
            `心跳失败-会话过期 => 考试剩余时间：${this.remainTime / 1000}`
          );
        } else {
          window._hmt.push(["_trackEvent", "正在考试页面", "心跳", "失败"]);
          this.logger({
            action: "发出心跳",
            error: "心跳失败",
            detail: `考试剩余时间：${this.remainTime / 1000} => ${error}`,
          });
          this.serverLog(
            "debug/S-008003",
            `心跳失败 => 考试剩余时间：${this.remainTime / 1000} => ${error}`
          );
        }
        this.heartbeatErrorNum++;
        if (this.heartbeatErrorNum >= 10) {
          // 心跳异常10次则退出考试
          clearInterval(this.heartbeatInterval);
          clearInterval(this.remainTimeInterval);
          window._hmt.push([
            "_trackEvent",
            "正在考试页面",
            "心跳",
            "失败10次-退出",
          ]);
          const redirectUrl = sessionStorage.getItem("redirectUrl");
          this.logger({
            action: "发出心跳",
            error: "心跳失败",
            detail: `失败10次-退出`,
          });
          console.log(`失败10次-退出`);
          this.$Modal.error({
            title: "网络连接异常",
            content: "退出考试",
            onOk: () => {
              if (redirectUrl) {
                window.location = redirectUrl;
              } else {
                this.$router.push(
                  "/login/" +
                    localStorage.getItem("domain") +
                    "?LogoutReason=心跳失败10次-退出"
                );
              }
            },
          });
          return;
        }
        this.retryHeartbeatTimeout = setTimeout(
          () => this.getRemainTimeFromServer(),
          10 * 1000
        );
      }
    },
    clearIntervals() {
      clearInterval(this.heartbeatInterval);
      clearInterval(this.remainTimeInterval);
      clearTimeout(this.retryHeartbeatTimeout);
      clearInterval(this.enhancedRemainTimeInterval);
    },
  },
};
</script>

<style scoped>
/* .remain-time {
  background-color: white;
  padding: 5px 10px;
  border-radius: 5px;
} */

.enhanced-remain-time {
  color: red;
}

.animated {
  animation-duration: 1s;
  animation-fill-mode: both;
  display: inline-block;
}

.animated.infinite {
  animation-iteration-count: infinite;
}

@keyframes pulse {
  from {
    transform: scale3d(1, 1, 1);
  }

  50% {
    transform: scale3d(1.05, 1.05, 1.05);
  }

  to {
    transform: scale3d(1, 1, 1);
  }
}

.pulse {
  animation-name: pulse;
}
</style>
