<template>
  <span style="display: flex; align-items: center; ">
    <span v-show="shouldShowAudio" @click="play">
      <Button
        v-if="!playing"
        type="primary"
        shape="circle"
        icon="ios-play"
        :disabled="playCount === 0"
      ></Button>
      <Button
        v-else
        type="primary"
        shape="circle"
        icon="md-pause"
        style="cursor: not-allowed;"
      ></Button>
    </span>
    &nbsp;
    <span v-show="shouldShowAudio">
      {{ formatTime(currentTime) }} / {{ formatTime(duration) }}
    </span>

    <span v-if="!shouldShowAudio" style="color: blueviolet;">
      音频下载中{{ downloadPercent }}%
    </span>
  </span>
</template>

<script>
import moment from "moment";

export default {
  name: "QuestionAudio",
  props: {
    src: {
      type: String,
      required: true,
    },
    name: {
      type: String,
      required: true,
    },
    playCount: {
      type: Number,
      required: true,
    },
  },
  data() {
    return {
      done: false,
      downloadPercent: 0,
      currentTime: 0,
      duration: 0,
      playing: false,
      context: null,
      buffer: null,
    };
  },
  computed: {
    shouldShowAudio() {
      return this.downloadPercent === 100;
    },
  },
  async created() {
    this.loadData();
  },
  beforeDestroy() {
    this.source && this.source.stop();
    if (this.context) {
      this.context.close();
      this.context = null;
    }
  },
  methods: {
    formatTime(seconds) {
      return moment.utc(seconds * 1000).format("mm:ss");
    },
    loadData() {
      this.context = new AudioContext();
      this.buffer;

      const loadDogSound = url => {
        var request = new XMLHttpRequest();
        request.open("GET", url, true);
        request.responseType = "arraybuffer";

        // Decode asynchronously
        request.onload = () => {
          this.context.decodeAudioData(
            request.response,
            buffer => {
              this.buffer = buffer;
              this.duration = Math.floor(this.buffer.duration);
              this.downloadPercent = 100;
              // console.log("load ... ");
            },
            () => {
              console.log("error load audio");
            }
          );
        };
        request.onprogress = e => {
          // console.log(e);
          // console.log(e.loaded / e.total);
          this.downloadPercent = Number((e.loaded / e.total) * 100).toFixed(2);
        };
        request.send();
      };

      loadDogSound(this.src);
    },
    async play() {
      if (this.playCount <= 0) {
        console.log("无播放次数");
        return;
      }
      if (this.playing) {
        console.log("正在播放，无法暂停");
        return;
      }
      this.$emit("played");
      // var audio = new Audio();
      // this.source = this.context.createMediaElementSource(audio); // creates a sound source

      // await this.context.decodeAudioData(this.buffer);
      this.context.close();
      this.context = new AudioContext();
      this.source = this.context.createBufferSource(); // creates a sound source
      this.source.buffer = this.buffer; // tell the source which sound to play
      this.source.connect(this.context.destination); // connect the source to the context's destination (the speakers)
      this.source.start(0); // play the source now
      // audio.play();
      this.playing = true;
      this.currentTime = 0;
      const progress = () => {
        // console.log(context.currentTime, buffer.duration);
        this.currentTime = Math.floor(this.context.currentTime);
        if (this.context.currentTime < this.buffer.duration) {
          requestAnimationFrame(progress);
        } else if (this.context.currentTime >= this.buffer.duration) {
          this.currentTime = 0;
          requestAnimationFrame(progress);
        }
      };
      requestAnimationFrame(progress);
      // note: on older systems, may have to use deprecated noteOn(time);
      this.source.onended = () => {
        // console.log(e, "ended");
        this.playing = false;
        this.currentTime = 0;
        // this.$emit("ended", this.name);
      };
    },
  },
};
</script>
