<template>
  <div class="sound-record-preview">
    <div v-if="type === 'big' && file_url" class="audio-slider-box audio-slider-box-big">
      <span class="audio-time">{{ secondFormatConversion(audio.current_time) }}</span>
      <el-slider
        v-model="play_value"
        class="audio-slider"
        :format-tooltip="formatProcessToolTip"
        @change="changeCurrentTime"
      />
      <span class="audio-time">{{ audio_allTime }}</span>
    </div>
    <div :class="['sound-record-wrapper', 'sound-record-wrapper-' + type]" :style="{ justifyContent: position }">
      <div class="sound-item sound-item-luyin">
        <img
          v-if="microphoneStatus"
          :src="require('../../../../../assets/record-ing-hasBg.png')"
          class="voice-play"
          @click="microphone"
        />
        <span v-else class="sound-item-span" @click="microphone">
          <SvgIcon icon-class="mic-line" :size="iconSize" class="record" />
        </span>

        <label v-if="type === 'big'" :class="['record-time', microphoneStatus ? 'record-ing' : '']">
          {{ microphoneStatus ? secondFormatConversion(recordTimes) : '录音' }}
        </label>
      </div>
      <div v-if="type === 'small' && file_url" class="sound-item audio-slider-box">
        <span class="audio-time">{{ secondFormatConversion(audio.current_time) }}</span>
        <el-slider
          v-model="play_value"
          class="audio-slider"
          :format-tooltip="formatProcessToolTip"
          @change="changeCurrentTime"
        />
        <span class="audio-time">{{ audio_allTime }}</span>
      </div>

      <label v-if="type === 'small' && !file_url" :class="['record-time', microphoneStatus ? 'record-ing' : '']">
        {{ audio.paused ? '' : '-' }}{{ secondFormatConversion(recordTimes) }}
      </label>
      <div class="sound-item">
        <span :class="['sound-item-span sound-item-btn', wavBlob ? '' : 'not-url']" @click="playMicrophone">
          <SvgIcon :icon-class="iconClass" :size="iconSize" :class="['audio-play-btn']" />
        </span>
        <label v-if="type === 'big'" class="tips">回放</label>
      </div>
      <div class="sound-item">
        <span :class="['sound-item-span sound-item-btn', wavBlob ? '' : 'not-url']" @click="delectWav">
          <SvgIcon icon-class="delete" :size="iconSize" :class="['delete-btn']" />
        </span>
        <label v-if="type === 'big'" class="tips">删除</label>
      </div>
    </div>
    <audio
      :ref="wavBlob"
      :src="file_url"
      preload="metadata"
      @loadedmetadata="onLoadedmetadata"
      @timeupdate="onTimeupdate"
      @canplaythrough="oncanplaythrough"
    ></audio>
  </div>
</template>

<script>
import Recorder from 'js-audio-recorder'; // 录音插件

import { GetStaticResources, GetFileStoreInfo } from '@/api/app';
import { secondFormatConversion } from '@/utils/transform';

export default {
  name: 'SoundRecordPreview',
  props: {
    wavBlob: {
      type: String,
      default: '',
    },
    type: {
      type: String,
      default: 'big',
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    // 播放按钮位置
    position: {
      type: String,
      default: 'left',
    },
  },
  data() {
    return {
      secondFormatConversion,
      recorder: new Recorder({
        sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
        sampleRate: 16000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000
        numChannels: 1, // 声道，支持 1 或 2， 默认是1
      }),
      timer: null, // 计时器
      microphoneStatus: false, // 是否录音
      hasMicro: '', // 录音后的样式class
      playtime: 0, // 播放时间
      recordTimes: 0,
      file_url: '',
      recordTime: 0,
      audio: {
        paused: true,
        playing: false,
        // 音频当前播放时长
        current_time: 0,
        // 音频最大播放时长
        max_time: 0,
        isPlaying: false,
        loading: false,
      },
      play_value: 0,
      audio_allTime: null, // 展示总时间
    };
  },
  computed: {
    iconClass() {
      return this.audio.paused ? 'play-fill' : 'pause';
    },
    iconSize() {
      return this.type === 'big' ? 24 : 16;
    },
  },
  watch: {
    wavBlob: {
      handler(val) {
        if (!val) {
          this.file_url = '';
          this.recordTime = 0;
          this.recordTimes = 0;
          return;
        }
        GetFileStoreInfo({ file_id: val }).then(({ file_url, media_duration }) => {
          this.file_url = file_url;
          this.recordTime = media_duration;
          this.recordTimes = JSON.parse(JSON.parse(media_duration));
        });
      },
      immediate: true,
    },
  },
  mounted() {
    this.$refs[this.wavBlob].addEventListener('ended', () => {
      this.audio.paused = true;
    });
    this.$refs[this.wavBlob].addEventListener('pause', () => {
      this.audio.paused = true;
    });
    this.$refs[this.wavBlob].addEventListener('play', () => {
      this.audio.paused = false;
    });
  },
  methods: {
    playMicrophone() {
      if (this.wavBlob) {
        let totalTime = JSON.parse(JSON.stringify(this.recordTime));
        if (this.audio.paused) {
          this.hasMicro = 'active';
          // this.$refs.audio.pause();
          // this.$refs.audio.load();
          this.$refs[this.wavBlob].play();
          if (this.recordTimes === 0) {
            this.recordTimes = JSON.parse(JSON.stringify(this.recordTime));
            this.playtime = 0;
          }
          clearInterval(this.timer);
          this.timer = setInterval(() => {
            if (this.playtime < totalTime) {
              this.playtime += 1;
              this.recordTimes = totalTime - this.playtime;
            } else {
              this.playtime = 0;
              this.recordTimes = JSON.parse(JSON.stringify(this.recordTime));
              clearInterval(this.timer);
            }
          }, 1000);
        } else {
          this.$refs[this.wavBlob].pause();
          this.hasMicro = 'normal';
          clearInterval(this.timer);
        }
      }
    },
    // 开始录音
    microphone() {
      if (navigator && navigator.mediaDevices) {
        const constraints = { audio: true }; // 设置只获取音频流
        navigator.mediaDevices
          .getUserMedia(constraints)
          .then(() => {
            if (!this.audio.paused) {
              this.$refs[this.wavBlob].pause();
              this.audio.paused = true;
            }
            if (this.disabled) return;
            if (this.microphoneStatus) {
              this.hasMicro = 'normal';
              this.recorder.stop();
              clearInterval(this.timer);
              // 录音结束，获取取录音数据
              let wav = this.recorder.getWAVBlob(); // 获取 WAV 数据
              this.microphoneStatus = false;
              let reader = new window.FileReader();
              reader.readAsDataURL(wav);
              reader.onloadend = () => {
                let MethodName = 'file_store_manager-SaveFileByteBase64Text';
                let data = {
                  base64_text: reader.result.replace('data:audio/wav;base64,', ''),
                  file_suffix_name: 'mp3',
                };
                GetStaticResources(MethodName, data).then((res) => {
                  if (res.status === 1) {
                    this.$emit('update:wavBlob', res.file_id);
                  }
                });
              };
            } else {
              this.hasMicro = '';
              this.$emit('update:wavBlob', '');
              // 开始录音
              this.recorder.start();
              this.microphoneStatus = true;
              this.recordTimes = 0;
              clearInterval(this.timer);
              this.timer = setInterval(() => {
                this.recordTimes += 1;
              }, 1000);
            }
          })
          .catch(() => {
            this.$message.warning('请打开浏览器录音权限');
          });
      } else {
        this.$message.warning('该浏览器不支持录音');
      }
    },
    // 删除录音
    delectWav() {
      this.$refs[this.wavBlob].pause();
      this.hasMicro = '';
      this.microphoneStatus = false;
      this.playtime = 0;
      this.recordTimes = 0;
      clearInterval(this.timer);
      this.$emit('update:wavBlob', '');
    },
    // 进度条格式化toolTip
    formatProcessToolTip(index) {
      let indexs = parseInt((this.audio.max_time / 100) * index);
      return secondFormatConversion(indexs);
    },
    // 点击 拖拽播放音频
    changeCurrentTime(value) {
      let audioId = this.wavBlob;
      this.$refs[audioId].play();
      this.audio.playing = true;
      this.$refs[audioId].currentTime = parseInt((value / 100) * this.audio.max_time);
    },
    // 音频加载完之后
    onLoadedmetadata(res) {
      this.audio.max_time = parseInt(res.target.duration);
      this.audio_allTime = this.audio.max_time ? secondFormatConversion(this.audio.max_time) : '00:00';
    },
    // 当音频当前时间改变后，进度条也要改变
    onTimeupdate(res) {
      let audioId = this.wavBlob;
      this.audio.current_time = res.target.currentTime;
      this.play_value = (this.audio.current_time / this.audio.max_time) * 100;
      if (this.audio.current_time * 1000 > this.ed) {
        this.$refs[audioId].pause();
      }
    },
    onTimeupdateTime(res, playFlag) {
      if (!res && res !== 0) return;
      let audioId = this.wavBlob;
      this.$refs[audioId].currentTime = res;
      this.play_value = (res / this.audio.max_time) * 100;
      if (playFlag) {
        let audio = document.getElementsByTagName('audio');
        audio.forEach((item) => {
          if (item.id !== audioId) {
            item.pause();
          }
        });
        this.$refs[audioId].play();
      }
    },
    oncanplaythrough() {
      this.audio.loading = false;
    },
  },
};
</script>

<style lang="scss" scoped>
.sound-record-wrapper {
  display: flex;
  column-gap: 18px;
  align-items: center;

  .sound-item {
    text-align: center;

    .sound-item-span {
      display: block;
      width: 48px;
      height: 48px;
      padding: 12px;
      font-size: 0;
      cursor: pointer;
      background: #ededed;
      border-radius: 80px;

      &.not-url {
        color: #a1a1a1;
        cursor: not-allowed;
      }
    }

    &-luyin {
      .sound-item-span {
        color: #fff;
        background-color: #7346d3;
      }

      .voice-play {
        display: block;
        width: 48px;
        height: 48px;
        cursor: pointer;
      }
    }

    .tips {
      display: block;
      margin-top: 4px;
      font-size: 14px;
      font-weight: 400;
      line-height: 20px;
      color: rgba($color: #000, $alpha: 50%);
    }
  }

  .record-time {
    display: block;
    margin-top: 4px;
    font-size: 14px;
    line-height: 20px;
    color: rgba(0, 0, 0, 50%);
  }

  &-small {
    column-gap: 8px;

    .sound-item {
      .sound-item-span {
        width: 32px;
        height: 32px;
        padding: 8px;
      }

      .voice-play {
        width: 32px;
        height: 32px;
      }
    }

    .record-time {
      min-width: 40px;
      margin-top: 0;
      text-align: center;
    }
  }
}

.audio-slider-box {
  display: flex;
  column-gap: 8px;
  align-items: center;

  .audio-time {
    min-width: 35px;
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
  }

  .audio-slider {
    width: 82px;
    height: 32px;

    :deep .el-slider__runway {
      height: 4px;
      margin: 14px 0;
      background-color: #dadada;
    }

    :deep .el-slider__button {
      width: 4px;
      height: 4px;
      background-color: #000;
      border: none;
    }

    :deep .el-slider__bar {
      height: 4px;
      background-color: #000;
    }

    :deep .el-slider__button-wrapper {
      top: -16px;
    }
  }

  &-big {
    width: 280px;
    height: 40px;
    padding: 4px 12px;
    margin: 16px auto;
    background-color: #ededed;
    border-radius: 28px;

    .audio-slider {
      width: 170px;
    }
  }
}
</style>
