<template>
  <div class="videoWrapper">
    <video ref="videoRef" autoplay muted class="video-js video-content" :poster="poster" disablePictureInPicture>
      <source :src="urlWithToken" />
    </video>
    <img class="loading" :src="loadingImg" v-show="loading" />
  </div>
</template>

<script setup lang="ts">
  import { onMounted, onBeforeUnmount, watch, ref, computed } from 'vue';
  import mpegts from 'mpegts.js';
  import { storeToRefs } from 'pinia';
  import { useUserStore } from '@/store/modules/user';
  import loadingImg from '@/assets/images/nine-square-grid/loading.gif';

  const props = defineProps<{
    url: string;
    poster?: string;
  }>();

  const userStore = useUserStore();
  const { token } = storeToRefs(userStore);

  let player: mpegts.Player | null;
  let lastDecodedFrames = 0; // 10s前的解码帧数
  let currentDecodedFrames = 0; // 当前解码帧数
  let loadingTimeout = 0;

  const videoRef = ref<HTMLVideoElement | null>(null);

  const loading = ref(true);

  const urlWithToken = computed(() => {
    if (!props.url) return '';

    return props.url;
  });

  const handleLoadeddata = () => {
    loading.value = false;
  };

  const initPlay = () => {
    if (!props.url || !videoRef.value || !token.value) {
      return;
    }

    const videoElement = videoRef.value;
    lastDecodedFrames = 0;
    currentDecodedFrames = 0;
    player = mpegts.createPlayer(
      {
        type: 'flv',
        isLive: true,
        hasAudio: false,
        url: urlWithToken.value,
      },
      {
        liveBufferLatencyChasing: true,
        /**
         * 控制直播视频流在缓冲区中允许的最大延迟时间。
         * 较小的值使播放更接近实时，但可能会因为网络波动或数据传输不及时导致播放卡顿。
         * 较大的值则会允许更多的缓冲，这样可以更好地应对网络波动，减少卡顿的可能性，但会增加播放延迟。
         */
        liveBufferLatencyMaxLatency: 4,
      },
    );

    videoElement.removeEventListener('loadeddata', handleLoadeddata);
    videoElement.addEventListener('loadeddata', handleLoadeddata);

    player.attachMediaElement(videoElement);
    player.load();
    player.on(mpegts.Events.ERROR, (e, detail, data) => {
      loading.value = true;
      console.log('视频加载错误类型', e);
      console.log('视频加载错误详情类型', detail);
      console.log('视频加载错误信息', data);
      // 当发生error时，这里会发生死循环，所以要注销掉。 interval方式中已经包含了此种错误的处理
      // reloadPlayer();
    });
    player.on(mpegts.Events.RECOVERED_EARLY_EOF, () => {
      console.log('视频播放结束');
      loading.value = true;
    });
    player.on(mpegts.Events.STATISTICS_INFO, (e) => {
      // console.log("视频播放信息", e.decodedFrames);
      const frame = e.decodedFrames || 0;
      handleLoading(frame);
      currentDecodedFrames = frame;
    });
    // player.play();
    setTimeout(() => {
      player?.play() as Promise<void>;
      console.log('视频play()触发');
    }, 50);
  };

  /** 处理loading信息 */
  const handleLoading = (nextFrame: number) => {
    if (currentDecodedFrames === nextFrame) {
      if (loadingTimeout) return;
      loadingTimeout = window.setTimeout(() => {
        loading.value = true;
        loadingTimeout = 0;
      }, 6000);
    } else {
      clearTimeout(loadingTimeout);
      loadingTimeout = 0;
      loading.value = false;
    }
  };

  const interval = setInterval(() => {
    if (currentDecodedFrames === lastDecodedFrames) {
      console.log('视频播放卡顿，10s前解码帧数为 ' + lastDecodedFrames + ' ，当前解码帧数为 ' + currentDecodedFrames);

      reloadPlayer();
    }
    lastDecodedFrames = currentDecodedFrames;
  }, 15000);

  const destroyPlayer = () => {
    // liveLoaded.value = false;
    if (player) {
      console.log('视频判断需要销毁');
      player!.pause();
      player!.unload();
      player!.detachMediaElement();
      console.log('视频播放器销毁');
      player!.destroy();
      player = null;
    }
  };

  onMounted(() => {
    initPlay();
  });

  const reloadPlayer = () => {
    loading.value = true;
    destroyPlayer();
    setTimeout(() => {
      initPlay();
    }, 100);
  };

  //切换播放url
  watch(
    () => props.url,
    () => {
      if (props.url) {
        reloadPlayer();
      }
    },
    {
      deep: true,
    },
  );

  onBeforeUnmount(() => {
    destroyPlayer();
    clearInterval(interval);
    clearTimeout(loadingTimeout);
  });
</script>

<style scoped lang="less">
  .video-content {
    width: 100%;
    height: 100%;
    background-color: transparent !important;
    object-fit: contain; // 0729fill->contain: 应急处置-指挥中心按需修改，若有其余地方使用出错再行修改
  }

  .videoWrapper {
    width: 100%;
    height: 100%;
    display: inline-block;
    position: relative;
  }

  .loading {
    position: absolute;
    z-index: 1;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    width: 60px;
  }
</style>
