<template>
  <div
    class="o-video is-ratio--16_9"
    :class="{ offline: !online, mask: !isPlaying, controls, floating, fullscreen: isFullscreen }"
    @mousemove="onMouseMove"
    @click.stop="onClick"
  >
    <template v-if="online">
      <video
        ref="video"
        class="o-video__player o-simple-video"
        :poster="poster"
        autoplay
        muted
        @play="onVideoPlay"
        @pause="onVideoPause"
        @waiting="onVideoWaiting"
        @playing="onVideoPlaying"
        @error="onVideoError"
        @ended="onVideoEnded"
      />
      <div class="o-video__mask">
        <div
          class="l-flex--row center o-video__btn u-pointer"
          @click.stop="onPlayOrPause"
        >
          <i :class="statusIconClass" />
        </div>
      </div>
    </template>
    <div
      v-if="controls"
      class="l-flex--row c-footer u-font-size--sm"
    >
      <div class="l-flex__fill c-sibling-item u-ellipsis">
        {{ device.name }}
      </div>
      <slot
        name="controls"
        :can-play="canPlay"
        :on-full-screen="onFullScreen"
        :waiting-or-loading="loading || waiting"
        :online="online"
        :is-playing="isPlaying"
      >
        <template v-if="online">
          <i
            v-if="loadingQuality"
            class="c-sibling-item el-icon-loading"
          />
          <div
            v-else
            class="l-flex__none c-sibling-item o-quality-menu u-pointer"
            @click.stop="toggleQualityMenu"
          >
            <div
              v-if="showQualityMenu"
              class="o-quality-menu__list u-font-size--sm u-text--center"
              @click.stop
            >
              <div
                v-for="item in qualities"
                :key="item.value"
                class="o-quality-menu__item has-active"
                :class="{ 'u-color--success': quality.value === item.value }"
                @click.stop="changeQuality(item)"
              >
                {{ item.label }}
              </div>
            </div>
            <span class="has-active">
              {{ quality.label }}
            </span>
          </div>
          <i
            class="c-sibling-item el-icon-full-screen has-active"
            @click.stop="onFullScreen"
          />
        </template>
      </slot>
    </div>
  </div>
</template>

<script>
import {
  GATEWAY,
  Quality
} from '@/constant.js'
import {
  authCode,
  getRecordConfig,
  addRecordConfig,
  updateRecordConfig,
  getDevice
} from '@/api/device.js'
import playerMixin from '../player.js'

export default {
  name: 'DevicePlayer',
  mixins: [playerMixin],
  props: {
    device: {
      type: Object,
      required: true
    },
    checkOnline: {
      type: [Boolean, String],
      default: false
    },
    useInitial: {
      type: [Boolean, String],
      default: false
    }
  },
  data () {
    return {
      online: false,
      floating: true,
      qualities: [
        { value: 'f', label: '标清' },
        { value: 'ff', label: '高清' },
        { value: 'fff', label: '超清' }
      ],
      loadingQuality: true,
      showQualityMenu: false,
      quality: null,
      recordConfig: null
    }
  },
  computed: {
    deviceOnline () {
      return this.device.onlineStatus === 1
    },
    canPlay () {
      return !this.loading && !this.needReset
    }
  },
  watch: {
    deviceOnline (val) {
      if (this.checkOnline) {
        return
      }
      this.updateOnlineStatus(val)
    },
    isFullscreen () {
      this.onMouseMove()
    }
  },
  created () {
    this.$delayMoveTimer = -1
    this.$checkTimer = -1
  },
  mounted () {
    if (this.checkOnline && !this.useInitial) {
      this.createPlayer()
    } else {
      this.updateOnlineStatus(this.deviceOnline)
    }
  },
  beforeDestroy () {
    clearTimeout(this.$delayMoveTimer)
    clearTimeout(this.$checkTimer)
    this.hideQualityMenu()
  },
  methods: {
    onClick () {
      this.$emit('click', this.device)
    },
    onMouseMove () {
      if (this.keep) {
        return
      }
      clearTimeout(this.$delayMoveTimer)
      this.floating = false
      if (!this.isFullscreen) {
        this.$delayMoveTimer = setTimeout(() => {
          this.floating = true
        }, 3000)
      }
    },
    onVideoReset () {
      this.recordConfig = null
      this.$playerInfo = null
    },
    getRecordConfig () {
      this.loadingQuality = true
      getRecordConfig(this.device.id, { custom: true }).then(
        ({ data }) => {
          if (data) {
            this.loadingQuality = false
            this.onUpdateRecordConfig(data)
          } else {
            this.setRecordConfig(this.qualities[0])
          }
        },
        () => {
          this.loadingQuality = false
          this.onVideoDestroyByError('获取回采配置失败')
        }
      )
    },
    onUpdateRecordConfig (data) {
      const { videoWidth } = data
      const key = Object.keys(Quality).find(key => Quality[key].videoWidth === videoWidth) || 'fff'
      this.quality = this.qualities.find(({ value }) => value === key) || this.qualities[0]
      this.recordConfig = data
      this.onCreatePlayer()
    },
    setRecordConfig (quality) {
      this.loadingQuality = true
      ;(this.recordConfig ? updateRecordConfig : addRecordConfig)({
        deviceId: this.device.id,
        ...Quality[quality.value]
      }, { custom: true }).then(
        ({ data }) => {
          this.loadingQuality = false
          this.destroyPlayer()
          this.onUpdateRecordConfig(data)
        },
        () => {
          this.loadingQuality = false
          if (!this.recordConfig) {
            this.onVideoDestroyByError('设置初始回采配置失败')
          }
        }
      )
    },
    hideQualityMenu () {
      if (this.showQualityMenu) {
        this.showQualityMenu = false
        document.removeEventListener('click', this.hideQualityMenu)
      }
    },
    toggleQualityMenu () {
      if (this.showQualityMenu) {
        this.hideQualityMenu()
      } else {
        document.addEventListener('click', this.hideQualityMenu)
        this.showQualityMenu = true
      }
    },
    changeQuality (quality) {
      if (this.quality.value !== quality.value) {
        this.setRecordConfig(quality)
      } else if (this.needReset) {
        this.createPlayer()
      }
      this.hideQualityMenu()
    },
    getAuthCode () {
      this.$playerInfo = null
      authCode(this.recordConfig.stream, { custom: true }).then(
        ({ data }) => {
          this.$playerInfo = data
          this.onCreatePlayer()
        },
        () => {
          this.onVideoDestroyByError('获取授权失败')
        }
      )
    },
    updateOnlineStatus (online) {
      this.online = online
      if (online) {
        this.$nextTick(this.createPlayer)
      } else {
        this.hideQualityMenu()
        this.onVideoReset()
        this.destroyPlayer()
      }
    },
    createPlayer () {
      if (this.$timer === null) {
        return
      }
      this.loading = true
      if (this.checkOnline) {
        clearTimeout(this.$checkTimer)
        getDevice(this.device.id, { custom: true }).then(
          ({ data }) => {
            if (this.$timer === null) {
              return
            }
            if (data) {
              const online = data.onlineStatus === 1
              this.online = online
              if (online) {
                this.$nextTick(this.onCreatePlayer)
              } else {
                this.hideQualityMenu()
                this.destroyPlayer()
                this.onVideoReset()
                this.checkOnlineStatus(5000)
              }
            }
          },
          () => {
            if (this.$timer === null) {
              return
            }
            this.checkOnlineStatus(2000)
          }
        )
      } else {
        this.onCreatePlayer()
      }
    },
    onCreatePlayer () {
      if (this.$timer === null) {
        return
      }
      if (!this.recordConfig) {
        this.getRecordConfig()
        return
      }
      // if (!this.$playerInfo) {
      //   this.getAuthCode()
      //   return
      // }
      // const { vhost = '__defaultVhost__', token, timestamp, expire } = this.$playerInfo
      // if (Number(timestamp) + Number(expire) * 1000 <= Date.now()) {
      //   this.getAuthCode()
      //   return
      // }
      // this.playUrl(`${GATEWAY}/live/${this.recordConfig.stream}.flv?vhost=${vhost}&authorization=${token}&timestamp=${timestamp}&expire=${expire}`)
      this.playUrl(`${GATEWAY}/live/${this.recordConfig.stream}.flv?vhost=__defaultVhost__`)
    },
    checkOnlineStatus (delay = 5000) {
      clearTimeout(this.$checkTimer)
      this.$checkTimer = setTimeout(this.createPlayer, delay + Math.random() * delay | 0)
    }
  }
}
</script>

<style lang="scss" scoped>
.o-quality-menu {
  display: inline-block;
  position: relative;
  padding: 0 $padding--xs;
  z-index: 1;

  &__list {
    position: absolute;
    right: 0;
    bottom: 100%;
    width: 100%;
    margin-bottom: $spacing--2xs;
    border-radius: $radius;
    background-color: rgba(#000, 0.85);
    z-index: -1;
  }

  &__item {
    padding: $padding--2xs 0;
  }
}
</style>
