<template>
  <div class="faceRecognition">
    <img :src="src" alt="" v-show="false" ref="img">
    <!-- style="position: fixed; left: 0;top: 0;background: #FFF;z-index: 999;" -->
    <video
      v-show="false"
      ref="video"
      autoplay
      playsinline
    ></video>
    <div class="box d-flex align-center justify-center" ref="box" :style="`width: ${size.width}`">
      <canvas ref="canvas"></canvas>
      <template v-if="ready">
        <div class="box-tool d-flex align-center justify-center">
          <div class="item" @click="handleTake">
            <v-icon color="#FFF" size="36">mdi mdi-camera</v-icon>
          </div>
        </div>
        <div class="close" @click="$emit('close')">
          <v-icon color="#FFF" size="36">mdi mdi-close-circle</v-icon>
        </div>
      </template>

      <div v-if="showImg" class="imgBox d-flex align-center justify-center" @click="showImg = false">
        <!-- <div class="faceItem" v-for="(detection, index) in detections" :key="index" :style="`left:${detection.x}px;top:${detection.y}px;font-size:14px;color: blue`">{{ index }}</div> -->
        <img :src="src" alt="" :width="size.width" :height="size.height">
      </div>
    </div>

    <v-overlay :value="loading" opacity="0">
      <v-progress-linear
        color="white"
        indeterminate
        rounded
        height="10"
        style="width: 200px;"
      ></v-progress-linear>

    </v-overlay>
    <v-overlay :value="checkLoading" opacity="0">
      <div class="cover">
        <div class="cover-move"></div>
      </div>
    </v-overlay>
  </div>
</template>

<script>
// import * as faceapi from 'face-api.js'
import { uploadImg } from '@/api/glass'
export default {
  name: 'm-camera',
  data () {
    return {
      videoStream: null,
      animationId: null,
      src: '',
      checkLoading: false,
      loading: true,
      ready: false,
      faceShape: '',
      showImg: false,
      detections: []
    }
  },
  inject: ['size'],
  mounted () {
    this.$nextTick(() => {
      this.resizeCanvas()
      // this.loadModels()
      this.startCamera()
    })
  },
  methods: {
    oGetUserMedia (constraints) {
      const getUserMedia = navigator.mediaDevices?.getUserMedia ||
                          navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia ||
                          navigator.oGetUserMedia

      return new Promise((resolve, reject) => {
        if (!getUserMedia) {
          return reject(new Error('getUserMedia is not supported.'))
        }
        getUserMedia.call(navigator.mediaDevices || navigator, constraints)
          .then(resolve)
          .catch(reject)
      })
    },
    async startCamera () {
      this.loading = true
      this.ready = false
      try {
        this.videoStream = await this.oGetUserMedia({
          video: { facingMode: 'user' }
        })

        const video = this.$refs.video
        this.$refs.video.srcObject = this.videoStream
        video.onloadedmetadata = () => {
          video.play()
          this.drawToCanvas()
          this.loading = false
          this.ready = true
        }
      } catch (error) {
        this.$emit('reject', '相机打开失败')
      }
    },
    resizeCanvas () {
      const canvas = this.$refs.canvas
      canvas.width = this.size.width
      canvas.height = this.size.height
    },
    drawToCanvas () {
      const canvas = this.$refs.canvas
      const context = canvas.getContext('2d')
      const video = this.$refs.video

      // 将视频画面绘制到canvas上
      const drawFrame = () => {
        context.clearRect(0, 0, canvas.width, canvas.height)

        // 获取视频宽高比
        const videoAspectRatio = video.videoWidth / video.videoHeight
        const canvasAspectRatio = canvas.width / canvas.height
        let drawWidth, drawHeight, drawX, drawY
        // 判断对比率
        if (videoAspectRatio > canvasAspectRatio) {
          drawWidth = canvas.height * videoAspectRatio
          drawHeight = canvas.height
          drawX = (canvas.width - drawWidth) / 2
          drawY = 0
        } else {
          drawHeight = canvas.height
          drawWidth = canvas.width
          drawX = 0
          drawY = (canvas.width / videoAspectRatio - canvas.height) / 2
        }
        // 保存当前画布状态
        context.save()

        // 水平翻转画布
        context.scale(-1, 1)
        // 在翻转的画布上绘制视频，调整绘制位置
        context.drawImage(video, -drawX - drawWidth, drawY, drawWidth, drawHeight)

        // 恢复画布状态
        context.restore()

        this.animationId = requestAnimationFrame(drawFrame)
      }

      // 开始动画循环
      drawFrame()
    },
    async handleTake () {
      this.checkLoading = true
      const canvas = this.$refs.canvas
      // 使用 toDataURL 方法获取 Base64 图像数据
      const img = canvas.toDataURL('image/png') // 可以选择其他格式如 'image/jpeg'
      try {
        this.src = img
        this.showImg = true
        const response = await fetch(img)
        const blob = await response.blob()
        const file = new File([blob], 'canvasImage.png', { type: 'image/png' })
        const query = new FormData()
        query.append('file', file)
        const { data } = await uploadImg(query)
        this.$emit('photo', data, img)
      } catch (error) {
        this.checkLoading = false
        this.showImg = false
        console.log(error)
        this.$emit('error', error)
      }
    }
    // handleReTake () {
    //   this.src = ''
    //   this.showImg = false
    //   this.$modal.hide('face')
    // }
  },
  beforeDestroy () {
    // 停止视频流和动画
    if (this.videoStream) {
      this.videoStream.getTracks().forEach(track => track.stop())
    }
    if (this.animationId) {
      cancelAnimationFrame(this.animationId)
    }
  }
}
</script>

<style lang="less" scoped>
.cover {
  @width: 300px;
  @height: 350px;
  width: @width;
  height: @height;
  margin: 0 auto;
  @color: #FFF;
  background: linear-gradient(@color, @color) left top,
      linear-gradient(@color, @color) left top,
      linear-gradient(@color, @color) right top,
      linear-gradient(@color, @color) right top,
      linear-gradient(@color, @color) left bottom,
      linear-gradient(@color, @color) left bottom,
      linear-gradient(@color, @color) right bottom,
      linear-gradient(@color, @color) right bottom;
  background-repeat: no-repeat;
  background-size: 8px 24px, 24px 8px;
  position: relative;
  &-move {
    height: 10px;
    width: 100%;
    top: 0;
    left: 0;
    position: absolute;
    background: linear-gradient(45deg, rgba(255,255,255,0), #fff, rgba(255,255,255,0));
    animation: pathTriangle 1s linear infinite;
  }

  @keyframes pathTriangle {
    0% {
      top: 0;
    }
    100% {
      top: calc(@height - 10px);
    }
  }
}

.faceRecognition {
  font-size: 14px;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.box {
  margin: 0 auto;
  background: #000;
  position: relative;
  height: 100%;
  &-tool {
    position: absolute;
    height: 150px;
    width: 100%;
    bottom: 0;
    left: 0;
    font-size: 16px;
    z-index: 99;
    .item {
      padding: 10px;
      border: 1px solid #999;
      border-radius: 90px;
      cursor: pointer;
    }
  }
  .close {
    z-index: 99;
    position: absolute;
    cursor: pointer;
    right: 10px;
    top: 10px;
    width: 40px;
    height: 40px;
    text-align: center;
    line-height: 40px;
  }
  .imgBox {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
  }
}

.faceItem {
  position: absolute;
  width: 5px;
  height: 5px;
  z-index: 999;
  background: greenyellow;
}

</style>
