<template>
  <div class="recording">
    <div class="recording-content" v-if="isRecording">
      <div class="header-top" :style="{width: progress + '%'}"></div>
      <div class="header-line" :style="{width: progress + '%'}">
        <span class="line1 animation"></span>
        <span class="line2 animation"></span>
        <span class="line3 animation"></span>
        <span class="line4 animation"></span>
        <span class="line5 animation"></span>
        <span class="line6 animation"></span>
        <span class="line7 animation"></span>
        <span class="line8 animation"></span>
        <span class="line9 animation"></span>
        <span class="line10 animation"></span>
        <span class="line11 animation"></span>
        <span class="line12 animation"></span>
        <span class="line13 animation"></span>
        <span class="line14 animation"></span>
        <span class="line15 animation"></span>
        <span class="line16 animation"></span>
        <span class="line17 animation"></span>
        <span class="line18 animation"></span>
        <span class="line19 animation"></span>
        <span class="line20 animation"></span>
        <span class="line1 animation"></span>
        <span class="line2 animation"></span>
        <span class="line3 animation"></span>
        <span class="line4 animation"></span>
        <span class="line5 animation"></span>
        <span class="line6 animation"></span>
        <span class="line7 animation"></span>
        <span class="line8 animation"></span>
        <span class="line9 animation"></span>
        <span class="line10 animation"></span>
        <span class="line11 animation"></span>
        <span class="line12 animation"></span>
        <span class="line13 animation"></span>
        <span class="line14 animation"></span>
        <span class="line15 animation"></span>
        <span class="line16 animation"></span>
        <span class="line17 animation"></span>
        <span class="line18 animation"></span>
        <span class="line19 animation"></span>
        <span class="line20 animation"></span>
        <span class="line1 animation"></span>
        <span class="line2 animation"></span>
        <span class="line3 animation"></span>
        <span class="line4 animation"></span>
        <span class="line5 animation"></span>
        <span class="line6 animation"></span>
        <span class="line7 animation"></span>
        <span class="line8 animation"></span>
        <span class="line9 animation"></span>
        <span class="line10 animation"></span>
        <span class="line10 animation"></span>
        <span class="line11 animation"></span>
        <span class="line12 animation"></span>
        <span class="line13 animation"></span>
        <span class="line14 animation"></span>
        <span class="line15 animation"></span>
        <span class="line16 animation"></span>
        <span class="line17 animation"></span>
        <span class="line18 animation"></span>
        <span class="line19 animation"></span>
        <span class="line20 animation"></span>
      </div>
      <div class="progress" :style="{left: progress + '%'}"></div>
      <p class="time">{{ time }}</p>
    </div>
    <div class="stop-content" v-else-if="!isRecording && isStop">
      <p class="time">{{ time }}</p>
      <div class="header-line">
        <span class="line1 animation"></span>
        <span class="line2 animation"></span>
        <span class="line3 animation"></span>
        <span class="line4 animation"></span>
        <span class="line5 animation"></span>
        <span class="line6 animation"></span>
        <span class="line7 animation"></span>
        <span class="line8 animation"></span>
        <span class="line9 animation"></span>
        <span class="line10 animation"></span>
        <span class="line11 animation"></span>
        <span class="line12 animation"></span>
        <span class="line13 animation"></span>
        <span class="line14 animation"></span>
        <span class="line15 animation"></span>
        <span class="line16 animation"></span>
        <span class="line17 animation"></span>
        <span class="line18 animation"></span>
        <span class="line19 animation"></span>
        <span class="line20 animation"></span>
        <span class="line1 animation"></span>
        <span class="line2 animation"></span>
        <span class="line3 animation"></span>
        <span class="line4 animation"></span>
        <span class="line5 animation"></span>
        <span class="line6 animation"></span>
        <span class="line7 animation"></span>
        <span class="line8 animation"></span>
        <span class="line9 animation"></span>
      </div>
    </div>
    <div class="content" v-else>
      <img src="./img/body.png" alt="">
      <p class="text">点击下方按钮开始录音</p>
      <p class="text">为了保证效果，请靠近手机讲话哦~</p>
    </div>
    <div class="footer">
      <span v-if="isRecording || isStop" @click="restart">重新开始</span>
      <img v-if="isStop" :src="`${$cdn}video/${!isPlay ? 'play-icon' : 'stop-img'}.png`" @click="play">
      <img v-else :src="`${$cdn}video/${isRecording ? 'stop-img' : 'microphone'}.png`"  @click="record">
      <!-- :src="isRecording ? stopImg : microphone" -->
      <span v-if="isStop" @click="save">保存</span>
    </div>
    <audio style="opacity: 0; visibility: hidden;" :src="audioSrc" @ended="onAudioEnd"></audio>
  </div>
</template>

<script>
import Recorder from 'recorder-core'
import 'recorder-core/src/engine/mp3'
import 'recorder-core/src/engine/mp3-engine'
import microphone from './img/microphone.png'

export default {
  name: 'recording',
  data() {
    return {
      isRecording: false,
      progress: 0,
      microphone,
      isPlay: false,
      isStop: false,
      blobFile: null,
      time: '00:00:00',
      counterDownTime: 0,
      recorder: null,
      counterDownTimeout: null,
      timingTimeout: null,
      audioSrc: '',
      audio: null,
      duration: 0
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.audio = document.querySelector('audio')
    })
  },

  methods: {
    record() {
      if (!this.isRecording) {
        this.duration = 0
        this.recorder = Recorder({
          type: 'mp3',
          sampleRate: 16000,
          bitRate: 16,
          onProcess(buffers, powerLevel, bufferDuration, bufferSampleRate, newBufferIdx, asyncEnd) {
            //可利用extensions/waveview.js扩展实时绘制波形
          }
        })

        this.recorder.open(() => {
          this.recorder.start()
          this.isRecording = true
          this.timing()
        })
      } else {
        this.stop()
      }
    },

    blobToDataURI(blob) {
      return new Promise((resolve) => {
        var reader = new FileReader()
        reader.readAsDataURL(blob)
        reader.onload = function (e) {
          resolve(e.target.result)
        }
      })
    },

    save() {
      if (!this.blobFile) {
        return this.$u.toast(`请录音`)
      }

      this.blobToDataURI(this.blobFile).then(res => {
        uni.$emit('record', res)
        uni.navigateBack({
          delta: 1
        })
      })
    },

    onAudioEnd() {
      this.isPlay = false
    },

    stop() {
      this.isRecording = false
      this.isStop = true
      clearTimeout(this.timingTimeout)
      this.recorder.stop((blob, duration) => {
        this.blobFile = blob

        var durationObj = this.$dayjs.duration(this.counterDownTime * 1000)
        this.duration = this.counterDownTime
        var hours = durationObj.hours() > 9 ? durationObj.hours() : '0' + durationObj.hours()
        var min = durationObj.minutes() > 9 ? durationObj.minutes() : '0' + durationObj.minutes()
        var seconds = durationObj.seconds() > 9 ? durationObj.seconds() : '0' + durationObj.seconds()

        this.time = hours + ':' + min + ':' + seconds
        console.log(blob, (window.URL || webkitURL).createObjectURL(blob), '时长:' + duration + 'ms')
        this.recorder.close()
        this.recorder = null
      }, msg => {
        console.log('录音失败:' + msg)
        this.recorder.close()
        this.recorder = null
      })
    },

    play() {
      if (!this.isPlay) {
        this.playAudio()
        this.counterDown()
      } else {
        this.isPlay = false
        clearTimeout(this.counterDownTimeout)
        this.audio.pause()
      }
    },

    playAudio() {
      this.isPlay = true
      if (!this.audioSrc) {
        this.audioSrc = (window.URL || webkitURL).createObjectURL(this.blobFile)
      }

      this.$nextTick(() => {
        this.audio.play()
      })
    },

    recodeStop() {
      this.recorder.stop((blob, duration) => {
        this.restart()
        this.blobFile = blob
        console.log(blob, (window.URL || webkitURL).createObjectURL(blob), '时长:' + duration + 'ms')
        this.recorder.close()
        this.recorder = null
      }, msg => {
        console.log('录音失败:' + msg)
        this.recorder.close()
        this.recorder = null
      })
    },

    restart() {
      this.time = '00:00:00'
      this.progress = 0
      this.blobFile = null
      this.isPlay = false
      this.isRecording = false
      clearTimeout(this.counterDownTimeout)
      clearTimeout(this.timingTimeout)
      this.counterDownTime = 0
      this.audioSrc = ''
      this.isStop = false
    },

    counterDown() {
      if (this.counterDownTime === -1) {
        clearTimeout(this.counterDownTimeout)
        this.counterDownTime = this.duration

        return false
      }

      var durationObj = this.$dayjs.duration(this.counterDownTime * 1000)
      var hours = durationObj.hours() > 9 ? durationObj.hours() : '0' + durationObj.hours()
      var min = durationObj.minutes() > 9 ? durationObj.minutes() : '0' + durationObj.minutes()
      var seconds = durationObj.seconds() > 9 ? durationObj.seconds() : '0' + durationObj.seconds()

      this.time = hours + ':' + min + ':' + seconds
      this.counterDownTime--
      this.counterDownTimeout = setTimeout(() => {
        this.counterDown()
      }, 1000)
    },

    timing() {
      this.progress = ((this.counterDownTime / 120) * 100).toFixed(2) > 100 ? 101 : ((this.counterDownTime / 120) * 100).toFixed(2)
      var durationObj = this.$dayjs.duration(this.counterDownTime * 1000)
      var hours = durationObj.hours() > 9 ? durationObj.hours() : '0' + durationObj.hours()
      var min = durationObj.minutes() > 9 ? durationObj.minutes() : '0' + durationObj.minutes()
      var seconds = durationObj.seconds() > 9 ? durationObj.seconds() : '0' + durationObj.seconds()

      this.time = hours + ':' + min + ':' + seconds
      this.counterDownTime++
      this.timingTimeout = setTimeout(() => {
        this.timing()
      }, 1000)
    }
  }
}
</script>

<style lang="scss" scoped>
uni-page-body {
  background-color: #fff;
}

.recording {
  height: 100vh;
  overflow-y: hidden;

  .content {
    padding-top: 310px;
    text-align: center;

    img {
      width: 406px;
      height: 306px;
      margin-bottom: 48px;
    }

    .text {
      font-size: 30px;
      color: #999;
      line-height: 42px;
      text-align: center;
    }
  }

  .footer {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 168px;
    background: #F6F8FC;
    padding: 20px 86px;
    box-sizing: border-box;

    span {
      display: inline-block;
      width: 160px;
      height: 64px;
      background: #4E8EEE;
      border-radius: 32px;
      font-size: 30px;
      color: #fff;
      text-align: center;
      line-height: 64px;
      vertical-align: top;
      margin-top: 30px;
    }

    img {
      width: 128px;
      height: 128px;
      margin: 0 64px;
    }
  }

  .recording-content {
    position: relative;
    overflow: hidden;
  }

  .stop-content {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    height: calc(100% - 168px);

    .header-line {
      width: 380px;
    }

    .time {
      margin-top: 0;
      margin-bottom: 32px;
    }
  }

  .header-top {
    position: absolute;
    top: 16px;
    left: 0;
    height: 6px;
    background: url(img/top.png) repeat-x;
    background-size: auto 6px;
  }

  .time {
    width: 100%;
    margin-top: 208px;
    text-align: center;
    font-size: 96px;
    color: #000000;
    line-height: 134px;
  }

  .progress {
    position: absolute;
    top: 16px;
    left: 0;
    width: 2px;
    height: 128px;
    background: #3477EE;
  }

  .header-line {
    width: 100%;
    max-width: 100%;
    height: 128px;
    line-height: 128px;
    margin-top: 16px;
    overflow: hidden;
  }

  .animation {
    animation: note 0.24s ease-in-out;
    animation-iteration-count: infinite;
    animation-direction: alternate;
  }

  .header-line span {
    display: inline-block;
    width: 6px;
    height: 16px;
    margin: 0 6px;
    border: none;
    border-radius: 4px;
    background-color: #3476EE;
  }

  .header-line span.line1 {
    animation-delay: -1s;
  }

  .header-line span.line2 {
    animation-delay: -0.9s;
  }

  .header-line span.line3 {
    animation-delay: -0.8s;
  }

  .header-line span.line4 {
    animation-delay: -0.7s;
  }

  .header-line span.line5 {
    animation-delay: -0.6s;
  }

  .header-line span.line6 {
    animation-delay: -0.5s;
  }

  .header-line span.line7 {
    animation-delay: -0.4s;
  }

  .header-line span.line8 {
    animation-delay: -0.4s;
  }

  .header-line span.line9 {
    animation-delay: -0.2s;
  }

  .header-line span.line10 {
    animation-delay: -0.1s;
  }

  .header-line span.line11 {
    animation-delay: -1s;
  }

  .header-line span.line12 {
    animation-delay: -0.9s;
  }

  .header-line span.line13 {
    animation-delay: -0.8s;
  }

  .header-line span.line14 {
    animation-delay: -0.7s;
  }

  .header-line span.line15 {
    animation-delay: -0.6s;
  }

  .header-line span.line16 {
    animation-delay: -0.5s;
  }

  .header-line span.line17 {
    animation-delay: -0.4s;
  }

  .header-line span.line18 {
    animation-delay: -0.3s;
  }

  .header-line span.line19 {
    animation-delay: -0.2s;
  }

  .header-line span.line20 {
    animation-delay: -0.1s;
  }

  @keyframes note {
    from {
      transform: scaleY(1);
    }
    to {
      transform: scaleY(4);
    }
  }
}
</style>
