<template>
  <div class="hty-video" 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>
    <video :id="id" :style="videoStyle" ref="player" :src="signed_url" playsinline webkit-playsinline x5-video-player-type="h5" controls preload="metadata"></video>
  </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, showLoadingToast, showToast} from 'vant'
import useUser from "~/store/user";
import {HtyBaseRoles} from "~/types";
import {MediaHelper} from '~/utils/index'
import useRefResource from "~/store/ref-resource";

enum VideoStates {
  Initial, Playing, Paused
}

export default defineComponent({
  name: "hty-video",
  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
    },
    videoStyle(): 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: VideoStates.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 HTMLVideoElement;
      el.play();
    }

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

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

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

    const signed_url = computedAsync(async () => (await MediaHelper.get_video_url(props.src)));

    let downloading = false;
    const download = async () => {
      if (downloading) return;
      downloading = true;
      const toast = showLoadingToast({ message: "处理中，请稍后再试", forbidClick: false, duration: 2000 });
      try {
        let marked_url = await download_resource(props.src, hty_id);
        if (marked_url) {
          let to_download = await MediaHelper.get_video_url(marked_url);
          if (!navigator.userAgent.includes('miniProgram')) {
            window.open(to_download, "_blank")
          } else {
            wx.miniProgram.navigateTo({
              url: "/pages/download/download?url=" + encodeURIComponent(to_download as string) + "&type=video",
              fail: (e: any) => {
                console.log('nav to download failed...', e)
              }
            });
          }
        } else {
          showToast("视频文件转码中，请稍后下载")
        }
      } finally {
        toast.close();
        downloading = false;
      }
    }

    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 video can show poster
        el.currentTime = 1
      })
      el.addEventListener("loadeddata", () => {
        console.log('loadeddata')
        if (state.status !== VideoStates.Playing) {
          el.currentTime = 0;
        }
      })
      el.addEventListener('play', () => {
        state.status = VideoStates.Playing
      })
      el.addEventListener('pause', () => {
        state.status = VideoStates.Paused
      })
      el.addEventListener('ended', () => {
        state.status = VideoStates.Initial
      })
    })


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

<style scoped lang="less">
  .hty-video {
    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;
      }
    }

    video {
      margin: 0 auto;
      display: block;
      width: auto;
      max-width: 100%;
      height: auto;
      max-height: calc(100% - 1rem);
    }
  }
</style>
