<template>
  <div class="hty-audio" v-show="signed_url" :style="containerStyle">
    <div class="control-bar" v-if="!simple" :style="controlBarStyle">
      <div class="rate-control">
        <van-tag type="primary" @click="setRate(1)">× 1</van-tag>
        <van-tag type="primary" @click="setRate(0.75)">0.75</van-tag>
        <van-tag type="primary" @click="setRate(0.5)">0.5</van-tag>
        <van-tag type="primary" @click="setRate(0.25)">0.25</van-tag>
        <van-tag type="primary" @click="setRate(1.5)">1.5</van-tag>
      </div>
      <div class="action-control">
        <i @click="jump(-5)" class="fa-solid fa-backward"></i>
        <i v-if="playing" @click="pause()" class="fa-solid fa-pause"></i>
        <i v-else @click="play" class="fa-solid fa-play"></i>
        <i @click="jump(5)" class="fa-solid fa-forward"></i>
        <i v-if="canDownload" @click="download()" class="fa-solid fa-download"></i>
      </div>
    </div>
    <audio :id="id" :style="audioStyle" ref="player" :src="signed_url" playsinline webkit-playsinline x5-audio-player-type="h5" controls preload="metadata"></audio>
  </div>
  <van-empty v-if="!signed_url" description="还没有视频" />
</template>

<script lang="ts">
// @ts-ignore
import wx from 'weixin-js-sdk';
import {computed, defineComponent, onMounted, reactive, ref, watch} from 'vue'
import { computedAsync } from '@vueuse/core'
import {Empty, Tag, Toast, showLoadingToast} from 'vant'
import useUser from "~/store/user";
import {HtyBaseRoles} from "~/types";
import { UpyunAccess } from '~/utils/upyun';
import useRefResource from "~/store/ref-resource";

enum AudioStates {
  Initial, Playing, Paused
}

export default defineComponent({
  name: "hty-audio",
  props: ['id', 'src', 'simple', 'radius', 'removable', 'height', 'downloadable'],
  components: {
    [Tag.name]: Tag,
    [Empty.name]: Empty
  },
  computed: {
    containerStyle() {
      let style: any = {};
      if (this.height) {
        style.height = this.height
      }
      return style;
    },
    controlBarStyle() {
      let style: any = {};
      if (this.removable) {
        style.paddingRight = "0.6rem";
      }
      if (this.radius && !this.simple) {
        let radius = this.radius + 'px'
        style = { ...style, borderTopLeftRadius: radius, borderTopRightRadius: radius }
      }
      return style
    },
    audioStyle(): any {
      if (this.radius) {
        let radius = this.radius + 'px'
        if (this.simple) {
          return { borderRadius: radius }
        }
        return { borderBottomLeftRadius: radius, borderBottomRightRadius: radius}
      }
      return {}
    }
  },
  methods: {
    stop() {
      let el = this.$refs.player as unknown as HTMLVideoElement;
      el.pause();
      el.currentTime = 0;
    }
  },
  setup(props) {
    const { store: {currentRole, current: {hty_id}}  } = useUser();
    const {download_resource} = useRefResource()

    const player = ref()
    const state = reactive({
      rate: 1.0,
      status: AudioStates.Initial
    })

    const setRate = (rate: number) => state.rate = rate

    const jump = (offset: number) => {
      let el = player.value as unknown as HTMLVideoElement;
      el.currentTime += offset;
    }


    const canDownload = computed(() => currentRole === HtyBaseRoles.TEACHER || props.downloadable)


    const play = () => {
      let el = player.value as unknown as HTMLAudioElement;
      el.play();
    }

    const pause = () => {
      let el = player.value as unknown as HTMLAudioElement;
      el.pause();
    }

    const fullscreen = () => {
      let el = player.value as unknown as HTMLAudioElement;
      el.requestFullscreen();
    }

    const playing = computed(() => state.status === AudioStates.Playing)

    const signed_url = computedAsync(async () => (await UpyunAccess.getSign(props.src)));

    const download = async () => {
      if (!navigator.userAgent.includes('miniProgram')) {
        window.open(signed_url.value, "_blank")
      } else {
        wx.miniProgram.navigateTo({
          url: "/pages/download/download?url=" + encodeURIComponent(signed_url.value as string) + "&type=audio",
          fail: (e: any) => {
            console.log('nav to download failed...', e)
          }
        });
      }
    }

    watch(() => state.rate, rate => {
      let el = player.value as unknown as HTMLVideoElement;
      el.playbackRate = rate || 1.0;
    })

    onMounted(() => {
      let el = player.value as unknown as HTMLVideoElement;
      el.addEventListener("loadedmetadata", () => {
        console.log('loadedmetadata')
        // set seek time to make sure audio can show poster
        el.currentTime = 1
      })
      el.addEventListener("loadeddata", () => {
        console.log('loadeddata')
        if (state.status !== AudioStates.Playing) {
          el.currentTime = 0;
        }
      })
      el.addEventListener('play', () => {
        state.status = AudioStates.Playing
      })
      el.addEventListener('pause', () => {
        state.status = AudioStates.Paused
      })
      el.addEventListener('ended', () => {
        state.status = AudioStates.Initial
      })
    })


    return { setRate, jump, play, pause, fullscreen, download, playing, player, canDownload, signed_url }
  }
});
</script>

<style scoped lang="less">
  .hty-audio {
    width: 100%;
    height: 100%;
    text-align: center;

    .control-bar {
      background: #d3d3d3;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      padding: 0.1rem 0.16rem;
      color: #1989fa;
      height: 1rem;

      .rate-control, .action-control {
        display: flex;
        align-items: center;
        justify-content: space-between;

        :deep(.van-tag) {
          font-family: serif;
          font-size: 12px;
          width: 36px;
          display: inline-block;
          text-align: center;

          &:not(:last-child) {
            margin-right: 0.1rem;
          }
        }
      }
      i {
        font-size: 0.32rem;
      }
    }

    audio {
      margin-top: 5px;
      display: block;
      width: 100%;
      height: 40px;
    }
  }
</style>
