<template>
  <div></div>
</template>

<script>
import * as faceapi from "face-api.js";
import { FACE_API_MODEL_PATH } from "@/constants/constants";

function getFaceDetectorOptions() {
  window.____hideMe =
    window.____hideMe ||
    new faceapi.TinyFaceDetectorOptions({
      inputSize: 320,
      scoreThreshold: 0.5,
    });
  return window.____hideMe;
  // return new faceapi.SsdMobilenetv1Options({ minConfidence: 0.8 });
  // return new faceapi.MtcnnOptions({ minFaceSize: 200, scaleFactor: 0.8 });
}

const detectTimeArray = [];
export default {
  name: "FaceTracking",
  async created() {
    await faceapi.nets.tinyFaceDetector.load(FACE_API_MODEL_PATH);
    // faceapi.nets.faceRecognitionNet.load(modelsPath);
    await faceapi.loadFaceLandmarkModel(FACE_API_MODEL_PATH);
    faceapi.tf.ENV.set("WEBGL_PACK", false);
  },
  async mounted() {
    let trackStarted = false;
    const that = this;

    async function trackHead() {
      const video = document.getElementById("video");
      if (
        video &&
        video.readyState === 4 &&
        faceapi.nets.tinyFaceDetector.params
      ) {
        trackStarted = true;
      } else {
        return;
      }
      console.log("start tracking ... ");
      await that.detectFaces();
    }
    this.trackHeadInterval = setInterval(() => {
      if (trackStarted) {
        clearInterval(this.trackHeadInterval);
      } else {
        trackHead();
      }
    }, 1000);
  },
  beforeDestroy() {
    clearInterval(this.trackHeadInterval);
    clearTimeout(this.warningTimeout);
    clearTimeout(this.detectFacesTimeout);
  },
  methods: {
    async detectFaces() {
      const detectStartTime = performance.now();
      const videoEl = document.getElementById("video");
      // this.___vWidth =
      //   this.___vWidth ||
      //   document.getElementById("video-container").clientWidth;

      const options = getFaceDetectorOptions();
      let result;

      try {
        result = await faceapi
          // .detectSingleFace(videoEl, options)
          .detectAllFaces(videoEl, options);
      } catch (e) {
        window._hmt.push(["_trackEvent", "正在考试页面", "实时人脸检测失败"]);
        throw e;
      }
      // console.log(result);

      const detectEndTime = performance.now();
      // console.log("WebGL: ", faceapi.tf.ENV.get("WEBGL_PACK"));
      console.log(
        "WebGL: ",
        faceapi.tf.ENV.get("WEBGL_PACK"),
        " single detect time: ",
        detectEndTime - detectStartTime,
        " result: ",
        result.length
      );

      if (detectTimeArray.length < 31) {
        // 仅捕获一部分检测次数
        detectTimeArray.push(detectEndTime - detectStartTime);
      }
      if (detectTimeArray.length === 31) {
        detectTimeArray.shift();
        const avg =
          detectTimeArray.reduce((a, b) => a + b, 0) / detectTimeArray.length;
        const roundAvg = Math.round(avg / 10) * 10;
        window._hmt.push([
          "_trackEvent",
          "正在考试页面",
          "实时人脸检测平均时长",
          roundAvg + "ms",
        ]);
        console.log(detectTimeArray);
        detectTimeArray.push(0, 0); // 避免再次达到push条件和上传条件
      }
      if (result.length >= 2) {
        this.$Message.warning({
          content: "请独立完成考试",
          duration: 5,
          closable: true,
        });
      }

      if (result.length === 0) {
        this.findFirst = !this.findFirst; // 两次才告警
        if (!this.findFirst) {
          this.$Message.warning({
            content: "请调整坐姿，诚信考试",
            duration: 5,
            closable: true,
          });
        }
      }

      if (
        (!result || result.length !== 1) &&
        !videoEl.classList.contains("video-warning")
      ) {
        videoEl.classList.add("video-warning");
        this.warningTimeout = setTimeout(function() {
          videoEl.classList.remove("video-warning");
        }, 3000);
      }

      this.detectFacesTimeout = setTimeout(() => this.detectFaces(), 5000);
    },
  },
};
</script>

<style>
@keyframes warning-people {
  0% {
    /* border: solid 5px white; */
    box-shadow: 0 0 100px white;
  }
  100% {
    /* border: solid 5px red; */
    box-shadow: 0 0 100px gold;
  }
}

.video-warning {
  animation: warning-people 3s infinite;
}
</style>
