<template>
  <div
    class="o-video"
    :class="{ offline: !online, mask: showMask }"
  >
    <template v-if="online">
      <video
        ref="video"
        class="o-video__player o-simple-video"
        :poster="poster"
        autoplay
        muted
        @pause="onPause"
        @play="onPlay"
      />
      <div class="o-video__mask">
        <div
          class="l-flex--row center o-video__btn u-pointer"
          @click="onClick"
        >
          <i :class="iconClass" />
        </div>
      </div>
    </template>
    <slot />
  </div>
</template>

<script>
import flvjs from 'flv.js'
import { authCode } from '@/api/camera'
import { GATEWAY } from '@/constant'
import videoPoster from '@/assets/video-poster.png'

export default {
  name: 'DevicePlayer',
  props: {
    device: {
      type: Object,
      required: true
    },
    autoplay: {
      type: [Boolean, String],
      default: false
    }
  },
  data () {
    return {
      poster: videoPoster,
      loading: false,
      refreshShow: false,
      paused: false
    }
  },
  computed: {
    showMask () {
      return this.loading || this.refreshShow || this.paused
    },
    iconClass () {
      if (this.loading) {
        return 'el-icon-loading'
      }
      if (this.refreshShow) {
        return 'el-icon-refresh'
      }
      return this.paused ? 'el-icon-video-play' : 'el-icon-video-pause'
    },
    online () {
      return this.device.activate === 2 && this.device.onlineStatus === 1
    }
  },
  created () {
    this.$timer = -1
    if (this.online) {
      this.getAuthCode()
    }
  },
  beforeDestroy () {
    this.destroyPlayer()
    this.$timer = null
  },
  methods: {
    onPause () {
      this.paused = true
    },
    onPlay () {
      this.paused = false
      if (this.loading) {
        this.loading = false
        if (!this.autoplay) {
          this.$player.pause()
        }
      }
    },
    onClick () {
      if (this.loading) {
        return
      }
      if (this.refreshShow) {
        if (this.$player) {
          this.destroyPlayer()
        }
        this.getAuthCode()
      } else {
        if (this.paused) {
          this.$player.play()
        } else {
          this.$player.pause()
        }
        this.paused = !this.paused
      }
    },
    getAuthCode () {
      if (this.loading) {
        return
      }
      this.loading = true
      authCode({ deviceId: this.device.id }).then(
        ({ data }) => {
          if (this.$timer !== null) {
            this.createPlayer(data)
          }
        },
        () => {
          this.destroyPlayer()
        }
      )
    },
    createPlayer ({ timestamp, token, expire }) {
      if (flvjs.isSupported()) {
        const player = flvjs.createPlayer({
          type: 'flv',
          isLive: true,
          hasAudio: false,
          url: `${GATEWAY}/live/${this.device.id}.flv?authorization=${token}&timestamp=${timestamp}&expire=${expire}`
        })
        player.on(flvjs.Events.ERROR, e => {
          console.log('flvjs', this.device.name, flvjs.Events.ERROR, e)
          this.destroyPlayer()
          this.$message({
            type: 'warning',
            message: `${this.device.name} 视频流出错`
          })
        })
        player.on(flvjs.Events.METADATA_ARRIVED, () => {
          console.log('flvjs', this.device.name, flvjs.Events.METADATA_ARRIVED)
          clearTimeout(this.$timer)
        })

        try {
          this.refreshShow = false
          this.$player = player
          this.$timer = setTimeout(() => {
            if (this.loading) {
              this.destroyPlayer()
              this.$message({
                type: 'warning',
                message: `暂未获取到 ${this.device.name} 的视频流`
              })
            }
          }, 10000)
          player.attachMediaElement(this.$refs.video)
          player.load()
        } catch (error) {
          console.log('连接异常', error)
          this.destroyPlayer()
        }
      }
    },
    destroyPlayer () {
      clearTimeout(this.$timer)
      this.loading = false
      this.refreshShow = true
      const player = this.$player
      if (player) {
        player.pause()
        player.unload()
        player.detachMediaElement()
        player.destroy()
        this.$player = null
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.o-video:hover {
  .o-video__mask {
    display: inline-block;
  }
}
</style>
