<template>
  <div class="faceWrap">
    <div class="wrap">
      <div class="box box1">
        <div class="title">
          原图
          <el-checkbox
            v-if="!defaultImage"
            v-model="reverse">
            <span style="color:#0075ff">视频翻转</span>
          </el-checkbox>
        </div>
        <div class=" con">
          <div
            class="see"
            ref="wrap">
            <!-- @loadedmetadata="fnRun" -->
            <div
              class="videoWrap"
              v-if="!defaultImage">
              <span class="txt">正在开启摄像头...</span>
              <video
                class="myVideo"
                :class="{reverse:reverse}"
                ref="video"
                muted
                loop
                autoplay
                playsinline
              ></video>
            </div>

            <div
              class="imageWrap"
              :class="{photo:!defaultImage}">
              <div style="position:relative">
                <img
                  :src="imageUrl"
                  ref="img"
                  class="img"
                  v-if="imageUrl">
                <canvas
                  class="canvas"
                  ref="canvas"
                  id="myCanvas" />
              </div>
            </div>

            <canvas
              class="canvas"
              ref="photoCanvas"
              style="display:none" />
          </div>
        </div>
      </div>

      <div class="box box2">
        <div class="title">
          拍照结果
        </div>
        <div class="con2">
          <div v-if="resultsImg.length>1">
            <h3>请选择照片</h3>
            <div class="imgs">
              <div
                class="img"
                :class="{active:currentResult&&currentResult.url===item.url}"
                @click="resultchange(item)"
                v-for="(item,index) in resultsImg"
                :key="index">
                <img
                  :src="item.url"
                  alt="">
              </div>
            </div>
          </div>

          <div
            v-if="currentResult"
            class="resultImage">
            <h3>选择的照片</h3>
            <img
              :src="currentResult.url"
              class="extra">
          </div>

          <!-- <el-tag
            v-if="message"
            :type="message.type"
          >
            {{ message.msg }}
          </el-tag> -->

          <el-upload
            action=""
            :show-file-list="false"
            :auto-upload="false"
            :on-change="handleAvatarSuccess">
            <el-button
              type="primary"
              :disabled="!isFinish && !!imageUrl"
              v-if="defaultImage"
              style="margin-top:20px">
              重新选择照片
            </el-button>
          </el-upload>

          <canvas
            ref="extraImage"
            style="display:none"></canvas>

          <template v-if="!defaultImage">
            <el-button
              type="primary"
              size="large"
              :disabled="!isFinish && !!imageUrl"
              @click="reTakePhoto"
              v-if="imageUrl">
              重新拍照
            </el-button>
            <el-button
              size="large"
              type="primary"
              @click="takePhoto"
              v-else>
              拍照
            </el-button>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>

<script>

export default {
  props: {
    defaultImage: {
      type: String,
      default: ''
    },
    value: {
      type: Object,
      default: () => null
    }
  },
  computed: {
  },
  data () {
    return {
      nets: 'ssdMobilenetv1', // 模型 tinyFaceDetector 、ssdMobilenetv1
      loading: true,
      imageUrl: '',
      options: null, // 模型参数
      withBoxes: true, // 边框or轮廓
      imgEl: null,
      canvasEl: null,
      extraImageUrl: '',
      resultsImg: [],
      currentResult: null,
      box: null,
      isFinish: false,
      scale: 0,
      reverse: true,
      constraints: {
        audio: false,
        video: {
          // ideal（应用最理想的）
          width: {
            min: 320,
            ideal: 1280,
            max: 1920
          },
          height: {
            min: 240,
            ideal: 720,
            max: 1080
          },
          // frameRate受限带宽传输时，低帧率可能更适宜
          frameRate: {
            min: 15,
            ideal: 30,
            max: 60
          },
          // 显示模式前置后置
          facingMode: 'environment'
        }
      }
    }
  },
  mounted () {
    this.videoEl = this.$refs.video
    this.canvasEl = this.$refs.canvas
    this.extraImage = this.$refs.extraImage
    this.photoCanvas = this.$refs.photoCanvas
  },
  methods: {
    fnOpen () {
      if (typeof window.stream === 'object') return
      this.box = null
      this.imageUrl = ''
      this.extraImageUrl = ''
      this.isFinish = false
      this.score = 0
      clearTimeout(this.timeout)
      this.timeout = setTimeout(() => {
        clearTimeout(this.timeout)
        navigator.mediaDevices
          .getUserMedia(this.constraints)
          .then(this.fnSuccess)
          .catch(this.fnError)
      }, 300)
    },
    // 成功启动视频媒体流
    fnSuccess (stream) {
      window.stream = stream // 使流对浏览器控制台可用
      this.videoEl.srcObject = stream
      this.videoEl.play()

      stream.getVideoTracks().forEach(i => {
        const setting = i.getSettings()
        this.realWidth = setting.width
        this.realHeight = setting.height
        console.log('实际视频输入设置', i.getSettings(), i.getConstraints())
      })
    },
    // 失败启动视频媒体流
    fnError (error) {
      console.log(error)
      this.$message.error('摄像头打开失败，' + error)
    },
    takePhoto () {
      console.log('我开始拍照了')
      this.photoCanvas.width = this.realWidth
      this.photoCanvas.height = this.realHeight

      const context = this.photoCanvas.getContext('2d')

      if (this.reverse) {
        const flipH = 1
        const flipV = 0

        var scaleH = flipH ? -1 : 1 // Set horizontal scale to -1 if flip horizontal
        var scaleV = flipV ? -1 : 1 // Set verical scale to -1 if flip vertical
        var posX = flipH ? this.realWidth * -1 : 0 // Set x position to -100% if flip horizontal
        var posY = flipV ? this.realHeight * -1 : 0 // Set y position to -100% if flip vertical

        context.save() // Save the current state
        context.scale(scaleH, scaleV) // Set scale to flip the image
        context.drawImage(this.videoEl, posX, posY, this.realWidth, this.realHeight) // draw the image
        context.restore() // Restore the last sa
      } else {
        context.drawImage(this.videoEl, 0, 0, this.realWidth, this.realHeight)
      }

      this.imageUrl = this.photoCanvas.toDataURL()
      this.currentResult = {
        url: this.imageUrl,
        width: this.photoCanvas.width,
        height: this.photoCanvas.height,
        score: 0
      }
      this.$emit('input', this.currentResult)
      this.isFinish = true
    },

    // 重拍照片
    reTakePhoto () {
      this.resultsImg = []
      this.currentResult = null
      this.box = null
      this.imageUrl = ''
      this.extraImageUrl = ''
      this.isFinish = false
      this.canvasEl && this.canvasEl.getContext('2d').clearRect(0, 0, this.canvasEl.width, this.canvasEl.height)
    },

    fnClose () {
      this.canvasEl
        .getContext('2d')
        .clearRect(0, 0, this.canvasEl.width, this.canvasEl.height)
      this.videoEl && this.videoEl.pause()
      clearTimeout(this.timeout)
      if (typeof window.stream === 'object') {
        window.stream.getTracks().forEach((track) => track.stop())
        window.stream = ''
        this.videoEl.srcObject = null
      }
    },

    resultchange (item) {
      this.$emit('input', item)
      this.currentResult = item
    },
    fnChange (e) {
      // console.log(e)
      this.resultsImg = []
      this.currentResult = null
      if (!e.target.files.length) return
      // 将文件显示为图像并识别
      faceapi.bufferToImage(e.target.files[0]).then((img) => {
        this.canvasEl.getContext('2d').clearRect(0, 0, this.canvasEl.width, this.canvasEl.height)
        this.imgEl.src = img.src
        this.fnRun()
      })
    },
    handleAvatarSuccess (res, list) {
      const isJPG = res.raw.type === 'image/jpeg' || res.raw.type === 'image/png'

      if (!isJPG) {
        this.$message.error('图片只能是 JPG或PNG 格式!')
        return
      }

      let reader = new FileReader()
      reader.readAsDataURL(res.raw)
      reader.onload = (e) => {
        this.imageUrl = e.target.result
      }
    }
  },
  watch: {
    defaultImage: {
      handler (val) {
        if (!val) return
        this.imageUrl = val
      },
      immediate: true
    }
  }
}
</script>

<style lang="scss" scoped>
.faceWrap {
  display: flex; padding: 10px;  margin: 0 auto; flex: 1;
}

.videoWrap {
  position: relative; width: 100%; height: 100%; color: #fff;  background: #000;
  .txt {
    position: absolute; top: 50%; left: 50%;transform: translate(-50%,-50%);
  }
  video {
    position: relative;  display: block; width: 100%; height: 100%;
  }
}

.el-button {
  width: 110px;margin-top: 10px;
}

.wrap {
  display: flex;  justify-content: space-between; flex: 1;
  h3{
    color: #0075ff; font-size: 16px; text-align: center; font-weight: bold;
  }

  .title {
    height: 40px;  padding: 0 20px; font-size: 18px; line-height: 40px; color: #0075ff; text-align: center; background: rgba(48, 77, 121, .1);
  }
  .box {
    display: flex;  width: 49%; flex-direction: column; background: #fff; border: 1px solid #ddd;
  }
  .box1 {
    width: 74%;
    .title {
      display: flex;  justify-content: space-between;
    }
  }
  .box2 {
    width: 24%;
  }
  .con {
    display: flex; padding: 20px; flex-direction: column; justify-content: center; align-items: center; flex: 1; width: 100%; box-sizing: border-box; overflow: auto;
  }

  .con2{
    padding: 20px; text-align: center; height: 100%; overflow: auto;
    .imgs{
      width: 100%; display: flex; flex-wrap: wrap; align-items: center; margin-bottom: 50px;
      .img{
        width: 30%; padding: 10px; background: #f0f0f0; flex: 1; margin: 10px;
      }
      img{
        width: 100%;
      }
    }

    .active{
      box-shadow: 0 0px 0px 5px red inset;
    }

    .resultImage{
      text-align: center; display: block;
      img{
        width: 100%;
      }
    }
  }
}
.see {
  position: relative; display: flex; width: 100%; overflow: hidden; flex: 1;justify-content: center; align-items: center;
}
.img,.myVideo {
  display: block;  max-width: 100%;
}
.imageWrap {
  position: relative;
}
.photo {
  position: absolute; top: 0; left: 0;display: flex; width: 100%;height: 100%; justify-content: center; align-items: center;
}
.canvas {
  position: absolute; top: 0; left: 0; transform-origin: 0 0;
}
.extra {
  max-width: 100%;
}

.reverse {
  transform: rotateY(180deg);
}

@keyframes scan {
  0% {
    top: 0;  box-shadow: 0 0 8px 10px rgba(170, 11, 23, .49);
  }
  50% {
    top: 50%;  box-shadow: 0 6px 8px 10px rgba(170, 11, 23, .49);
  }
  100% {
    top: 98%;  box-shadow: 0 -6px 8px 10px rgba(170, 11, 23, .49);
  }
}

.maskWrap {
  position: absolute; top: 0; left: 0;  width: 100%;height: 100%;
}
.mask {
  position: absolute;top: 50%;left: 50%; width: 50%; padding-bottom: 50%; box-shadow: 0 0 0 2000px rgba(0,0,0,.2); transform: translate(-50%,-50%); flex: 0 0 0; background: linear-gradient(to left, #16bd32, #16bd32) left top no-repeat, linear-gradient(to bottom, #16bd32, #16bd32) left top no-repeat, linear-gradient(to left, #16bd32, #16bd32) right top no-repeat, linear-gradient(to bottom, #16bd32, #16bd32) right top no-repeat, linear-gradient(to left, #16bd32, #16bd32) left bottom no-repeat, linear-gradient(to bottom, #16bd32, #16bd32) left bottom no-repeat, linear-gradient(to left, #16bd32, #16bd32) right bottom no-repeat, linear-gradient(to left, #16bd32, #16bd32) right bottom no-repeat;  background-size: 2px 20%, 20% 2px, 2px 20%, 20% 2px;
}

</style>
