<template>
<div class="play-content-video" ref="container">
  <div class="play-center" ref="box">
    <template v-if="chapterVideo">
      <div :class="['play-video', (state.pptBoxOnly ? 'play-video-hide' : ''), (state.calculatedSize ? '' : 'play-video-init-center')]">
        <template v-if="videoType !== '3'">
          <e-video
            ref="video"
            :lastTime="parseFloat((chapterVideo.progress && chapterVideo.progress.pt) || 0)"
            :width="videoFlash.videoWidth"
            :height="videoFlash.videoHeight"
            :username="videoFlash.username"
            :videoId="chapterVideo.video_origionalID"
            :videoSrt="(chapterVideo.video_subtitle || '')"
            @handlePlayTime="onVideoTimeChange"
            @handlePlayfinish="onVideoPlayFinish"
            :chapterVideo="chapterVideo"
          />
        </template>
        <template v-else>
          <e-video-h5
            ref="video"
            :lastTime="parseFloat((chapterVideo.progress && chapterVideo.progress.pt) || 0)"
            :width="videoFlash.videoWidth"
            :height="videoFlash.videoHeight"
            :username="videoFlash.username"
            :videoId="chapterVideo.id"
            :videoSrt="(chapterVideo.video_subtitle || '')"
            @handlePlayTime="onVideoTimeChange"
            @handlePlayfinish="onVideoPlayFinish"
            :chapterVideo="chapterVideo"
            :videoType="videoType"
            @changeVideoArr="changeVideoArr"
          />
        </template>
      </div>
      <div :class="['play-jiangyi', (state.pptBoxShow ? '' : 'hide')]">
        <template v-if="ppts.length">
          <e-ppt
            ref="ppt"
            :ppts="ppts"
            :currentIndex="state.pptIndex"
            @onVideoSyncTime="setVideoTime"
            @onPptOnly="togglePptBoxOnly"
            @onClose="togglePptBox"
          />
        </template>
      </div>
    </template>
    <template v-else>
      <p>课程视频数据不存在</p>
    </template>
  </div>
  <!-- 底部控制 -->
  <div class="play-footer">
    <div class="fl">
      <!-- <Link to={`/courses/${semesterId}/${courseId}/chapters/${prevChapterId || chapterId}`} class={`play-state play-state-prev ${prevChapterId?'': 'play-state-prev-disable'}`}>上一节</Link> -->
      <!-- <Link to={`/courses/${semesterId}/${courseId}/chapters/${nextChapterId || chapterId}`} class={`play-state play-state-next ${nextChapterId?'': 'play-state-next-disable'}`}>下一节</Link> -->
    </div>
    <div class="fr">
      <template v-if="chapterVideo.pdf">
        <em class="play-state play-state-ppt" ><a :href="chapterVideo.pdf" target="_blank">下载PPT</a></em>
      </template>
      <!-- <em class={`play-state play-state-check${curProgress == 100 ? '-active' : ''}`} onClick={this.handleOver} data-vid={video && video.id || ''} data-progress={curProgress} data-total={video && video.video_length || 1}>{curProgress == 100 ? '已学完' : '标记为已学完'}</em> -->
      <template v-if="ppts.length">
        <em :class="['play-state', ('play-state-ppt' + (state.pptBoxShow ? '-active' : ''))]" @click="togglePptBox">同步显示PPT</em>
      </template>
      <em :class='["play-state", ("play-state-check" + (state.skipBegin ? "-active" : ""))]' @click="toggleSkipBegin">始终跳过片头</em>
    </div>
  </div>
</div>
</template>

<script>
import eVideo from './video.vue'
import eVideoH5 from './videoH5.vue'
import ePpt from './ppt.vue'
import _ from 'lodash'

const PLAY_SPACE_WIDTH = 15
const PLAY_SPACE_HEIGHT = 10

/* 初始视频 宽、高 */
const VIDEO_DEFAULT_WIDTH = 550
const VIDEO_DEFAULT_HEIGHT = 360

/* 视频 定时 心跳记录器 默认时间 ms */
const HEART_TIME = 10000

export default {
  components: { eVideo, eVideoH5, ePpt },
  props: {
    chapterId: { type: String, require: false },
    chapterName: { type: String, require: false },
    chapterVideo: { type: Object, require: false },
    ppts: { type: Array, require: false, default: [] },
    sid: { type: String, require: false },
    cid: { type: String, require: false },
    id: { type: String, require: false },
    videoType: { type: String, require: false }
  },
  data () {
    return {
      state: {
        pptIndex: 0, // ppt 所在当前位置
        pptBoxOnly: false, // 仅展示ppt框
        pptBoxShow: false, // 展示ppt框
        skipBegin: /skip=1/.test(document.cookie), // 跳过片头
        calculatedSize: false // 是否以计算过播放位置的尺寸
      },
      /* video flash 参数传递 */
      videoFlash: {
        lastTime: null,
        speed: 1, // 默认播放速度
        isSeek: false, // 是否拖动进度条
        isFinish: false, // 是否播放完成
        queueFrames: [], // 存放所有视频帧的队列，上传成功清空一次。
        mapFrames: [], // 记录视频播放过的 所有帧 hash 表，数组 下标表示 视频对应帧 - 1，数组值 表示 播放过的帧，重复播 + 1
        videoWidth: VIDEO_DEFAULT_WIDTH,
        videoHeight: VIDEO_DEFAULT_HEIGHT,
        username: (window.G.UserInfo && window.G.UserInfo.username) || '',
        duration: 10000
      },
      /* 增加节流函数 对应 执行 */
      resizeVideo: null,
      /* 视频进度 统计 和 计算 */
      hearBeat: null,
      _rProgress: {},
      /* 检测视频 是否一直在播放，如果停止播放，则停止接口调用 */
      isPlaying: false
    }
  },
  mounted () {
    let size = this.getCalculateSize()
    if (size.video.w) {
      this.videoFlash.videoWidth = size.video.w
      this.videoFlash.videoHeight = size.video.h
    }
    /* 如果不存在 改变视频尺寸大小 节流执行函数 定义如下 */
    if (!this.resizeVideo) {
      this.resizeVideo = _.debounce(this.jdugeSize.bind(this), 200)
    }
    /* 延迟计算尺寸，因flash初始化需要时间 */
    setTimeout(this.jdugeSize, 600)
    /* 窗口resize，重置大小 */
    window.addEventListener('resize', this.resizeVideo)
    /* 增加 心跳 记录 视频学习时间 */
    this.createHeartTime(HEART_TIME)
  },
  destroyed () {
    window.removeEventListener('resize', this.resizeVideo)
    this.destroyHeartTime()
    /* 在定时器 被销毁时，再次执行 定时器，解决：播放过程中，突然退出当前页（非关闭） */
    this.hearBeatFunc(HEART_TIME)
  },
  watch: {
    id: {
      handler () {
        /* 重新点击时，刷新左侧，隐藏pptbox */
        /* 这里 理论上 应该 把所有 组件全部初始化，否则会出现部分数据是 上次同一个组件 但不同vid的 视频内容值 */
        if (this.id) {
          this.state.pptBoxShow = false
          this.state.pptBoxOnly = false
          this._rProgress = {}
          // this.videoFlash.lastTime = 0 // 这里 修改 最后时间不生效
          setTimeout(this.jdugeSize, 0)
        }
      }
    }
  },
  methods: {
    // toggle PPT播放框
    togglePptBox () {
      this.state.pptBoxShow = !this.state.pptBoxShow
      this.state.pptBoxOnly = false
      setTimeout(this.jdugeSize, 0)
    },
    // 仅显示ppt播放框
    togglePptBoxOnly () {
      this.state.pptBoxOnly = !this.state.pptBoxOnly
      setTimeout(this.jdugeSize, 0)
    },
    // 跳过片头
    toggleSkipBegin () {
      let skip = !this.state.skipBegin
      let d = new Date()
      d.setMonth(d.getMonth() + 1)
      document.cookie = 'skip=' + (+skip) + ';path=/;domain=.ezijing.com;expires=' + d.toGMTString()
      if (skip && this.$refs.video) {
        this.$refs.video.skipBegin()
      }
      this.state.skipBegin = skip
    },
    // 播放时间变更
    onVideoTimeChange (data) {
      let time = data.time
      /* 获取视频 总时长 */
      this.videoFlash.duration = data.duration || this.videoFlash.duration
      /* 获取 对应 播放 速度 和 是否 拖动 进度条 */
      this.videoFlash.speed = parseFloat(data.quality.split(' ')[1] || 1)
      this.videoFlash.isSeek = data.isSeek

      // 因视频播放完成后也会不断触发playing，因此比对上次时间
      if (this.videoFlash.lastTime === time) { return }
      this.videoFlash.lastTime = time

      this.isPlaying = true

      /* 将当前 获取的 每一帧 压缩 队列 */
      if (!data.isSeek) {
        this.videoFlash.queueFrames.push(time)
        // console.log(this.videoFlash.queueFrames)
      }
      // 判断ppt位置
      this.setPptIndexByTime(time)

      this.$emit('handlePlayTime', time) // 调用 父级方法，改变 sidebar ppt 对应 位置
    },
    // 视频播放结束，解决播放结束，但是没有等够 HEART_TIME 时间 就直接 关闭浏览器问题
    onVideoPlayFinish (data) {
      /* 视频播放完毕触发，然后判断 pt 累加时间 基本等于 视频观看时间时，才认为真正播放完成 */
      if (this.chapterVideo) {
        if (this._rProgress && this._rProgress.id) {
        } else {
          this._rProgress = _.assignIn({}, this.chapterVideo.progress)
          /* 增加 帧点 视频记录 精确粒度 到 秒 */
          let _arr = []
          let _len = this.chapterVideo.video_length || 1
          for (let i = 0; i < _len; i++) {
            _arr.push(0)
          }
          this.videoFlash.mapFrames = this._rProgress.map.length ? this._rProgress.map : _arr
          this._rProgress.map = this.videoFlash.mapFrames
        }
        if (this._rProgress.pt + ((HEART_TIME / 1000) * this.videoFlash.speed) >= data.time) {
          this.isPlaying = true // 这里 再设置一次 true ，只有为 true时 才能上传 进度
          this.hearBeatFunc(HEART_TIME)
        }
      }
    },
    changeVideoArr (obj) {
      this.$emit('changeVideoArr', obj)
    },
    /**
     * 根据时间设置ppt位置 - PPT 样式 控制
     */
    setPptIndexByTime (time) {
      const ppts = this.ppts || []
      let i = 0
      for (; i < ppts.length; i++) {
        if (time < ppts[i].ppt_point) { break }
      }
      if (this.state.pptIndex !== i - 1) {
        this.state.pptIndex = i - 1
      }
    },
    /**
     * 设置视频播放时间点 - video flash 控制
     */
    setVideoTime (time) {
      if (this.$refs.video) {
        this.$refs.video.setTimeTo(time)
      }
    },
    /**
     * 判断并设置尺寸位置
     */
    jdugeSize () {
      let box = this.$refs.box
      let size = this.getCalculateSize()
      let uh = 0
      let uw = 0
      if (this.state.pptBoxOnly) { // 仅ppt
        uw = size.ppt.w
        uh = size.ppt.h
        if (this.$refs.ppt) {
          this.$refs.ppt.setSize(uw, uh)
        }
      } else if (this.state.pptBoxShow) { // 同时显示video、ppt
        if (this.$refs.ppt) {
          this.$refs.ppt.setSize(size.ppt.w, size.ppt.h)
        }
        if (this.$refs.video) {
          this.$refs.video.setSize(size.video.w, size.video.h)
        }
        uw = size.ppt.w + size.video.w
        uh = size.video.h
      } else { // 只显示video
        uw = size.video.w
        uh = size.video.h
        if (this.$refs.video) {
          this.$refs.video.setSize(uw, uh)
        }
      }

      this.state.calculatedSize = true
      box.style.paddingLeft = '' + ((size.space.w - uw) / 2 + PLAY_SPACE_WIDTH) + 'px'
      box.style.paddingTop = '' + ((size.space.h - uh) / 2 + PLAY_SPACE_HEIGHT) + 'px'
    },
    /* 获取各个元素计算后的尺寸 */
    getCalculateSize () {
      let container = this.$refs.container
      let w = container.offsetWidth - PLAY_SPACE_WIDTH * 2
      let h = container.offsetHeight - 53 - PLAY_SPACE_HEIGHT * 2 // 减去底部操作条高度
      let videoRatio = 550 / 363
      let pptRatio = 336 / 236
      let r = {
        space: { w: w, h: h }, // 可容纳play的容器总大小
        video: { w: 0, h: 0 }, // 视频大小
        ppt: { w: 0, h: 0 } // ppt容器大小
      }

      if (this.state.pptBoxOnly) { // 仅ppt
        r.ppt.w = w < h * pptRatio ? w : h * pptRatio
        r.ppt.h = h < w / pptRatio ? h : w / pptRatio
      } else if (this.state.pptBoxShow) { // 同时显示video、ppt
        let halfW = w / 2
        let vw = halfW < h * videoRatio ? halfW : h * videoRatio
        let vh = h < halfW / videoRatio ? h : halfW / videoRatio
        let ph = vh
        let pw = ph * pptRatio
        r.video.w = vw
        r.video.h = vh
        r.ppt.w = pw
        r.ppt.h = ph
      } else { // 只显示video
        r.video.w = w < h * videoRatio ? w : h * videoRatio
        r.video.h = h < w / videoRatio ? h : w / videoRatio
      }
      return r
    },
    /* 计数器内部执行方法 */
    hearBeatFunc (_time) {
      if (this.chapterVideo && this.isPlaying) {
        if (this._rProgress && this._rProgress.id) {
        } else {
          this._rProgress = _.assignIn({}, this.chapterVideo.progress)
          /* 增加 帧点 视频记录 精确粒度 到 秒 */
          let _arr = []
          let _len = this.chapterVideo.video_length || 1
          for (let i = 0; i < _len; i++) {
            _arr.push(0)
          }
          this.videoFlash.mapFrames = this._rProgress.map.length ? this._rProgress.map : _arr
          this._rProgress.map = this.videoFlash.mapFrames
        }
        let _rProgress = this._rProgress
        let _duration = this.videoFlash.duration
        let tempTime = Math.min(this.videoFlash.lastTime, _duration)
        let _speed = this.videoFlash.speed
        let _isSeek = this.videoFlash.isSeek
        let _queue = this.videoFlash.queueFrames
        /* 第一次播放时 */
        if (_rProgress.cpt === 0 && _rProgress.mpt === 0 && _rProgress.pt === 0) {
          if (/skip=1/.test(document.cookie)) {
            _rProgress.pt = 7 // 跳过片头设置片头时间
          }
        }
        /* 拖动进度条，不记录时间 */
        if (!_isSeek) {
          /* 直接给出 增加定时器 循环定时 的每次 执行传输时间 */
          _rProgress.pt += (_time / 1000) * _speed
          /* cpt 和 mpt 应该没问题 */
          _rProgress.cpt = tempTime
          _rProgress.mpt = tempTime > _rProgress.mpt ? tempTime : _rProgress.mpt
          /* mpt 最大不能超过 总时长 */
          _rProgress.mpt = _rProgress.mpt > _duration ? _duration : _rProgress.mpt
          if (parseInt(_rProgress.mpt) > (parseInt(_duration) + 10000)) {
            this.$message.info('视频播放出错，请刷新页面重新观看。')
          }
          _rProgress.ps = _queue
          _rProgress.vid = this.id
          /* 调用接口执行刷新 */
          this.$emit('updateProgress', this._rProgress)
        }
        /* 实时监测 - 是否在播放中 */
        this.isPlaying = false
      }
    },
    /* 初始化定时器 */
    createHeartTime (time) {
      let _time = time || 10000
      this.destroyHeartTime()
      /* 增加 心跳 记录 视频学习时间 */
      this.hearBeat = setInterval(() => {
        this.hearBeatFunc(_time)
      }, _time)
    },
    /* 消除定时器 */
    destroyHeartTime () {
      this.hearBeat && clearInterval(this.hearBeat)
    }
  }
}
</script>
