/*
 *
 *    ┏┓　　　┏┓
 *  ┏┛┻━━━┛┻┓
 *  ┃　　　　　　　┃
 *  ┃　　　━　　　┃
 *  ┃　＞　　　＜　┃
 *  ┃　　　　　　　┃
 *  ┃...　⌒　...　┃
 *  ┃　　　　　　　┃
 *  ┗━┓　　　┏━┛
 *      ┃　　　┃
 *      ┃　　　┃
 *      ┃　　　┃
 *      ┃　　　┃  神兽保佑
 *      ┃　　　┃  代码无bug
 *      ┃　　　┃
 *      ┃　　　┗━━━┓
 *      ┃　　　　　　　┣┓
 *      ┃　　　　　　　┏┛
 *      ┗┓┓┏━┳┓┏┛
 *        ┃┫┫　┃┫┫
 *        ┗┻┛　┗┻┛
 * @Author: 木木
 * @LastEditors: 木木
 * @Date: 2022-06-02 09:46:06
 * @LastEditTime: 2022-06-02 10:41:42
 * @Description:调用摄像头识别二维码
 */

/**
 * @description: 初始化
 * @param {*} options {
 *  使用后置还是前置摄像头
 *  exact: 'environment' | 'user'
 *  获取摄像头视频像素 false 正常， true高清
 *  definition: boolean
 *  是否持续监听
 *  continue: boolean
 *  成功事件
 *  onSuccess: ():string => {}
 * }
 * @param {*} onSuccess ():string=>{} 成功事件
 * @return {*} MumuQrcode
 */
function MumuQrcode(options = {}, onSuccess) {
  // if (origin.indexOf('https') === -1) throw '请在 https 环境中调用摄像头。'
  if (origin.indexOf('https') === -1){
	  alert('请在 https 环境中调用摄像头。') 
	  window.history.go(-1)
	   return this
  } 

  this.exact = options.exact || 'environment'
  this.definition = options.definition || false
  this.continue = options.continue || false
  this.onSuccess = onSuccess || null

  this.__init()

  return this
}

MumuQrcode.prototype.__init = function () {
  var js = document.createElement('script')
  js.type = 'text/javascript'
  js.src = './mumu-qrcode/jsQR.js'
  document.body.append(js)
  js.addEventListener('load', () => {
    this.start()
  })
}
MumuQrcode.prototype.start = function () {
  this.windowWidth = document.documentElement.clientWidth || document.body.clientWidth
  this.windowHeight = document.documentElement.clientHeight || document.body.clientHeight

  this.video = null
  this.canvas = null
  this.canvas2d = null

  /** 闪光灯相关 */
  this.stream = null
  this.track = null
  this.isUseTrack = false
  this.trackStatus = false

  this.video = document.createElement('video')
  this.video.setAttribute('playsinline', 'true')
  this.video.setAttribute('webkit-playsinline', 'true')
  this.video.width = this.windowWidth
  this.video.height = this.windowHeight
  this.canvas = document.createElement('canvas')
  this.canvas.width = this.windowWidth
  this.canvas.height = this.windowHeight
  this.canvas2d = this.canvas.getContext('2d')

  const mumuQrcode = document.getElementById('mumuQrcode')
  this.mumuQrcode = mumuQrcode
  mumuQrcode.style =
    'position: absolute; top: 0;left: 0;  background-color: #333;width:' +
    this.windowWidth +
    'px;height:' +
    this.windowHeight +
    'px'
  mumuQrcode.append(this.canvas)
  mumuQrcode.append(this.video)

  const box = document.createElement('div')
  box.className = 'box'
  const line = document.createElement('div')
  line.className = 'line'
  const angle = document.createElement('div')
  angle.className = 'angle'
  box.append(line)
  box.append(angle)
  mumuQrcode.append(box)

  /** 闪关灯操作 */
  const box2 = document.createElement('div')
  box2.className = 'box2'
  box2.innerText = '打开闪光灯'
  this.box2Dom = box2
  box2.addEventListener('click', () => {
    if (this.trackStatus) {
      box2.innerText = '打开闪光灯'
    } else {
      box2.innerText = '关闭闪光灯'
    }
    this.trackStatus = !this.trackStatus
    this.openTrack()
  })

  this.addStyle()
  this.openScan()
}

MumuQrcode.prototype.openScan = function () {
  var width = this.transtion(this.windowHeight)
  var height = this.transtion(this.windowWidth)
  var videoParam = {
    audio: false,
    video: {
      facingMode: { exact: this.exact },
      width,
      height
    }
  }

  navigator.mediaDevices
    .getUserMedia(videoParam)
    .then((stream) => {
      this.video.srcObject = stream
      this.video.play()
      this.tick()

      this.stream = stream
      this.track = stream.getVideoTracks()[0]
      setTimeout(() => {
        const t = this.track.getCapabilities()
        this.isUseTorch = t.torch || null
        if (this.isUseTorch) return this.mumuQrcode.append(this.box2Dom)
      }, 500)
    })
    .catch((error) => {
		alert('设备不支持,请检查是否允许摄像头权限')
      // console.log('设备不支持,请检查是否允许摄像头权限', error)
      // throw error
    })
}

MumuQrcode.prototype.tick = function () {
  if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
    this.canvas2d.drawImage(this.video, 0, 0, this.windowWidth, this.windowHeight)
    const imageData = this.canvas2d.getImageData(0, 0, this.windowWidth, this.windowHeight)
    const codeRes = jsQR(imageData.data, imageData.width, imageData.height, {
      inversionAttempts: 'dontInvert'
    })

    if (codeRes) {
      this.drawLine(codeRes.location.topLeftCorner, codeRes.location.topRightCorner, '#FF3B58')
      this.drawLine(codeRes.location.topRightCorner, codeRes.location.bottomRightCorner, '#FF3B58')
      this.drawLine(
        codeRes.location.bottomRightCorner,
        codeRes.location.bottomLeftCorner,
        '#FF3B58'
      )
      this.drawLine(codeRes.location.bottomLeftCorner, codeRes.location.topLeftCorner, '#FF3B58')
      if (codeRes.data) {
        this.getData(codeRes.data)
      }
    }
  }
  requestAnimationFrame(this.tick.bind(this))
}

MumuQrcode.prototype.drawLine = function (begin, end, color) {
  this.canvas2d.beginPath()
  this.canvas2d.moveTo(begin.x, begin.y)
  this.canvas2d.lineTo(end.x, end.y)
  this.canvas2d.lineWidth = 4
  this.canvas2d.strokeStyle = color
  this.canvas2d.stroke()
}

MumuQrcode.prototype.getData = function (code) {
  this.onSuccess && this.onSuccess(code)
  if (this.continue) return
  if (!this.stream) return
  this.stream.getTracks().forEach((track) => {
    track.stop()
  })
}

MumuQrcode.prototype.openTrack = function () {
  if (!this.stream) return
  const ww = {
    advanced: [{ torch: this.trackStatus }]
  }
  this.track.applyConstraints(ww)
}

MumuQrcode.prototype.transtion = function (number) {
  return this.definition ? number * 1.6 : number
}

MumuQrcode.prototype.addStyle = function () {
  const style = document.createElement('style')
  style.innerHTML = `
  .box {
    width: 4rem;
    height: 4rem;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    overflow: hidden;
    border: 0.1rem solid rgba(0, 255, 51, 0.2);
    z-index: 10;
  }

  .box .line {
    height: calc(100% - 2px);
    width: 100%;
    background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #00ff33 211%);
    border-bottom: 3px solid #00ff33;
    transform: translateY(-100%);
    animation: radar-beam 2s infinite alternate;
    animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
    animation-delay: 1.4s;
  }

  .box:after,
  .box:before,
  .angle:after,
  .angle:before {
    content: '';
    display: block;
    position: absolute;
    width: 0.2rem;
    height: 0.2rem;
    z-index: 12;
    border: 0.1rem solid transparent;
  }

  .box:after,
  .box:before {
    top: 0;
    border-top-color: #00ff33;
  }

  .angle:after,
  .angle:before {
    bottom: 0;
    border-bottom-color: #00ff33;
  }

  .box:before,
  .angle:before {
    left: 0;
    border-left-color: #00ff33;
  }

  .box:after,
  .angle:after {
    right: 0;
    border-right-color: #00ff33;
  }

  @keyframes radar-beam {
    0% {
      transform: translateY(-100%);
    }
  
    100% {
      transform: translateY(0);
    }
  }

  .box2 {
    width: 2rem;
    height: 1rem;
    position: absolute;
    left: 50%;
    bottom: 1.2rem;
    transform: translate(-50%);
    z-index: 20;
    font-size: 0.28rem;
    display: flex;
    align-items: center;
    justify-content: center;
    color: aliceblue;
    background-color: rgba(000, 000, 000, 0.35);
  }
  `

  document.body.append(style)
}
