<template>
  <div class="video-player-wrapper">
    <div id="dplayer" ref="dplayerContainer"></div>
  </div>
</template>

<script>
import flvjs from 'flv.js'
import DPlayer from 'dplayer'
import { videoUrl } from '@/api/vod'

export default {
  name: 'VideoPlayerCard',
  props: {
    videoId: { type: String, required: true },
    videoData: { type: Object, required: true },
    userToken: { type: String, default: null },
    sendEvent: { type: Boolean, default: true }
  },
  data() {
    return {
      player: null,
      wsClient: null,
      wsUrl: null,
      wsReconnectLock: false,
      intervalEvent: null,
      danmakuApi: process.env.VUE_APP_SERVER_URL + '/api/comment/danmaku/'
    }
  },
  watch: {
    videoId: {
      immediate: true,
      handler(val) {
        if (val) this.loadVideoSource()
      }
    }
  },
  beforeDestroy() {
    this.destroyResources()
  },
  methods: {
    destroyResources() {
      if (this.player) this.player.destroy()
      if (this.wsClient) this.wsClient.close()
      if (this.intervalEvent) clearInterval(this.intervalEvent)
    },
    loadVideoSource() {
      this.destroyResources()
      videoUrl(this.videoId).then(res => {
        if (res.code === 0) {
          // 初始化 WebSocket
          if (this.userToken && this.sendEvent) {
            this.wsUrl = this.getWsUrl(this.videoId)
            this.initWebSocket()
          }
          // 初始化播放器
          const { type, urls, currentTime } = res.data
          if (type === 'mp4') {
            urls.forEach(u => u.type = 'normal')
            this.initMp4Player(urls, currentTime)
          } else if (type === 'flv') {
            this.$message.error('flv player not implement')
          }
        }
      })
    },
    getWsUrl(videoId) {
      const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'
      const host = window.location.host
      return `${protocol}${host}/ws/media?userToken=${this.userToken}&videoId=${videoId}`
    },
    initMp4Player(urls, pos) {
      this.player = new DPlayer({
        container: this.$refs.dplayerContainer,
        lang: 'zh-cn',
        screenshot: true,
        volume: 0.1,
        video: { pic: this.videoData.coverUrl, defaultQuality: 0, quality: urls },
        danmaku: { id: this.videoId, maximum: 10000, api: this.danmakuApi, token: this.userToken, bottom: '15%', unlimited: true }
      })
      this.player.seek(pos)
      this.bindEvents()
    },
    bindEvents() {
      let ended = false
      this.player.on('play', () => {
        if (this.sendEvent) {
          clearInterval(this.intervalEvent)
          this.intervalEvent = setInterval(() => {
            if (!ended) this.sendProgress(false)
          }, 5000)
        }
      })
      this.player.on('ended', () => {
        ended = true
        clearInterval(this.intervalEvent)
        this.sendProgress(true)
      })
    },
    sendProgress(isEnded) {
      const jsonData = {
        type: 'progress',
        direction: 'c2s',
        data: {
          mediaId: this.videoId,
          mediaType: 1,
          currentTime: this.player.video.currentTime,
          ended: isEnded
        }
      }
      if (this.wsClient && this.wsClient.readyState === WebSocket.OPEN) {
        this.wsClient.send(JSON.stringify(jsonData))
      }
    },
    initWebSocket() {
      this.wsClient = new WebSocket(this.wsUrl)
      this.wsClient.onopen = () => this.$emit('ws-status', true)
      this.wsClient.onclose = () => {
        this.$emit('ws-status', false)
        this.reconnect()
      }
      this.wsClient.onerror = () => this.reconnect()
      this.wsClient.onmessage = (evt) => {
        const msg = JSON.parse(evt.data)
        this.$emit('update-view-count', msg.viewCount)
      }
    },
    reconnect() {
      if (this.wsReconnectLock) return
      this.wsReconnectLock = true
      setTimeout(() => {
        this.initWebSocket()
        this.wsReconnectLock = false
      }, 5000)
    }
  }
}
</script>

<style scoped>
.video-player-wrapper {
  background: #000;
  border-radius: 4px;
  overflow: hidden;
  width: 100%;
}
#dplayer {
  height: 520px;
}
@media screen and (max-width: 768px) {
  #dplayer { height: 240px; }
}

/* 隐藏网页全屏按钮（左侧那个按钮） */
::v-deep .dplayer-full-in-icon {
  display: none !important;
}

/* 调整剩下的全屏按钮间距，防止右侧留白过大 */
::v-deep .dplayer-full-icon {
  margin-right: 5px !important;
}
</style>
