<template>
  <div
    class="pica-video"
    :style="{position: isFullScreen ? 'fixed' : ''}">
    <template v-if="isWechat">
      <video
        :id="vid"
        :src="url"
        :poster="poster"
        preload="metadata"
        webkit-playsinline
        playsinline
        x5-playsinline="true"
        x-webkit-airplay="allow"
        x5-video-player-type="h5"
        x5-video-player-fullscreen="false"
        mtt-playsinline="true"
        controlsList="nodownload"
        @loadedmetadata="loadedMetaData"
        @timeupdate="onTimeUpdate"
        @ended="onEnded"
        @error="onError"
      >
      </video>
      <div class="video-cover" @click="showControl = !showControl"></div>
      <!-- 控制栏 -->
      <div class="control-box" v-show="showControl">
        <div class="control-bar">
          <div class="btn-play" :class="{'btn-pause': isPaused}" @click="togglePlay"></div>
          <div class="progress-box" @click="setProgress">
            <div class="progress-inner">
              <div class="progress-bar" :style="progressBar"></div>
            </div>
            <div
              class="progress-ball"
              :style="{left: `${progressBall}%`}"
              @touchstart.stop="onBallStart"
              @touchmove.stop="onBallMove"
              @touchend.stop="onBallEnd">
            </div>
          </div>
          <div class="time-box">{{ playTime }}/{{ totalTime }}</div>
          <!-- <div class="rate-box" @click="showRate=true">
            倍速
            <div class="rate-list" v-show="showRate">
              <div
                class="rate-item"
                :class="{'rate-active': rate === curtRate}"
                v-for="rate in rates"
                :key="rate"
                @click.stop="selectRate(rate)">{{ rate }}</div>
            </div>
          </div> -->
          <div class="btn-screen" :class="{'btn-screen-mini': isFullScreen}" @click="onFullscreen"></div>
        </div>
      </div>
      <!-- 播放遮罩 -->
      <transition name="fade">
        <div v-show="logged && isPaused" class="cover cover-play" @click="togglePlay"></div>
      </transition>
      <!-- 播放错误 -->
      <transition name="fade">
        <div v-show="logged && showError" class="cover cover-error">
          <p>播放失败，请确认网络正常或重新进入页面</p>
        </div>
      </transition>
      <!-- 接续播放 -->
      <transition name="fade">
        <div v-show="showResume" class="cover cover-resume">
          <p>上次观看至{{ dealTime(history) }}，正在续播</p>
        </div>
      </transition>
      <!-- 弹窗放在外部处理 -->
      <slot></slot>
      <!-- 试看提示 -->
      <div class="proved-box" v-show="logged && showProved">
        可试看{{ dealTime(proved) }}，观看完整版请 <span @click="download">购买课程</span>
      </div>
      <!-- 重新播放，只有试看有 -->
      <div class="replay-box" v-show="showReplay" @click="onReplay">重新播放</div>
    </template>
    <img v-else class="default-img" src="~@/images/video/course_img.png" alt="" />
  </div>
</template>

<script>
/**
 * 不使用参数，调用两个方法；
 * switchUrl(opt)和switchUrlAndPlay(opt)
 * opt: {
 *   url, // 视频链接
 *   poster, // 封面
 *   proved, // 试看时长，单位秒
 *   history, // 上次观看时长，单位秒
 *   enable, // 是否可看
 * }
 * 暴露一个回调onVideoEnd，参数：
 * type => 1 播放结束，2 试看结束
*/
import { formatLeftTimeObj } from '@/utils';

export default {
  name: 'pica-video',
  props: {
    coverType: {
      type: Number,
      default: 0,
    },
    download: {
      type: Function,
      default: () => {}
    }
  },
  data() {
    return {
      url: '', // 视频链接
      poster: '', // 封面
      proved: 0, // 试看时长，单位秒
      history: 0, // 上次观看时长，单位秒
      enable: true, // 是否可看
      vid: '', // 唯一id
      playTime: '00:00', // 播放时长
      totalTime: '00:00', // 总时长
      isPaused: true, // 是否暂停
      isFullScreen: false, // 是否全屏
      showControl: true, // 显示控制栏
      progressBar: {}, // 进度条
      progressBall: 0, // 进度球
      rates: [2, 1.5, 1, 0.5],
      curtRate: 1,
      showRate: false,
      showProved: false, // 试看提示文字
      showError: false, // 播放错误
      showResume: false, // 继续播放
      showReplay: false, // 显示重播
      isWechat: true, // 微信环境
    }
  },
  computed: {
    logged() {
      return this.$store.getters.logged;
    },
  },
  created() {
    this.vid = `video_${this._uid}`;
    this.playTime = 0;
    const ua = navigator.userAgent;
    this.isWechat = ua.match(/(MicroMessenger)\/([\d.]+)/);
    this.isAndroid = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
  },
  mounted() {
    if (this.isWechat) {
      const player = document.getElementById(this.vid);
      player.addEventListener("timeupdate", this.onTimeUpdate, false);
      player.addEventListener("play", this.onPlay, false);
      player.addEventListener("pause", this.onPause, false);
      this.player = player;
    }
  },
  beforeDestroy() {
    this.timer && clearTimeout(this.timer);
    if (this.currentTime) {
      this.reportLeave();
    }
    if (!this.isPaused && !this.finish) {
      this.reportOnOff(2);
    }
  },
  methods: {
    // 被接管时,监听上报
    onPlay() {
      this.reportOnOff(1);
      this.isPaused = false;
      this.showProved = false;
    },
    onPause() {
      this.reportOnOff(2);
      this.reportLeave();
      this.isPaused = true;
    },
    togglePlay() {
      if (!this.logged) {
        this.$store.dispatch('goLogin');
        return;
      }
      if (!this.url || !this.enable) {
        return;
      }
      let isPaused = this.isPaused;
      // 试看，且超过时间
      if (this.proved && this.player.currentTime >= this.proved) {
        return;
      }
      this.player.style.display = 'block';
      if (isPaused) {
        this.player.play();
        this.playTime++;
        this.showProved = false;
      } else {
        this.player.pause();
      }
      // this.reportOnOff(isPaused ? 1 : 2); // 使用监听发送
      this.isPaused = !isPaused;
    },
    // 切换视频
    switchUrl(opts = {}) {
      if (!this.isWechat) {
        return;
      }
      this.player.style.display = 'block';
      const { url = '', poster = '', proved = 0, history = 0, enable = true } = opts;
      this.loaded = false;
      this.player.src = url;
      this.url = url;
      this.poster = poster;
      this.proved = proved;
      this.history = history;
      this.enable = enable;
      this.provedOver = false;
      this.finish = false;
      this.opts = opts;
      this.currentTime = null;
      this.duration = null;
      this.showProved = proved > 0;
      this.showReplay = false;
      if (this.showError) this.showError = false;
    },
    // 切换并播放
    switchUrlAndPlay(opts = {}) {
      if (!this.isWechat) {
        return;
      }
      if (!this.isPaused && !this.finish) {
        this.reportOnOff(2);
      }
      if (!this.finish) {
        this.reportLeave();
      }
      if (this.playTime === 0) {
        this.player.play();
      }
      this.switchUrl(opts);
      this.player.autoplay = true;
      if (!this.enable) {
        return;
      }
      const loop = () => {
        if (this.loaded) {
          this.player.play();
          if (!this.player.paused) {
            this.isPaused = false;
            // this.reportOnOff(1);
            this.showProved = false;
          }
          return null;
        } else {
          return setTimeout(() => {
            loop()
          }, 100);
        }
      }
      this.timer = loop();
    },
    // 重播
    onReplay() {
      this.$sendBuriedData({
        component_tag: `882#88213`
      });
      this.player.style.display = 'block';
      this.player.currentTime = 0;
      this.player.play();
      this.isPaused = false;
      // this.reportOnOff(1);
      this.$emit('onReplay');
      this.showReplay = false;
      this.provedOver = false;
    },
    // 加载完毕，获取总时长和音量。问题：移动端点击播放才会触发，且不一定会获取时长
    loadedMetaData() {
      let duration = this.player.duration;
      if (duration) {
        this.totalTime = this.formatTime(duration);
        this.loaded = true;
        if (this.history) {
          this.player.currentTime = this.history;
          this.showResume = true;
          setTimeout(() => {
            this.showResume = false;
          }, 2000);
        }
      }
    },
    // 播放中
    onTimeUpdate(e) {
      const { currentTime, duration } = e.target;
      // 试看，且超过时间
      if (this.proved && currentTime >= this.proved) {
        this.provedEnd();
      }
      if (this.provedOver) {
        return
      }
      if (currentTime) {
        this.playTime = this.formatTime(currentTime);
      }
      if (currentTime && duration) {
        this.setBarPosition(currentTime * 100 / duration, 'progressBar');
        this.currentTime = currentTime;
        this.duration = duration;
      }
      if (currentTime < 0.1 && !this.loaded) {
        this.loadedMetaData();
      }
    },
    // 设置进度条位置
    setBarPosition(percent, target) {
      this[target] = {
        transform: `translateX(${percent}%)`,
        '-webkit-transform': `-webkit-translateX(${percent}%)`,
        '-moz-transform': `-moz-translateX(${percent}%)`,
        '-ms-transform': `-ms-translateX(${percent}%)`,
      }
      if (target === 'progressBar' && !this.isMoveingBall) {
        this.progressBall = percent
      }
    },
    // 点击设置进度
    setProgress(e) {
      if (!this.url) {
        return;
      }
      const { offsetX } = e;
      const { width } = e.target.getBoundingClientRect();
      this.setProgressPosition(offsetX * 100 / width);
    },
    // 设置进度最终位置
    setProgressPosition(percent) {
      const duration = this.player.duration;
      // 试看，且超过时间
      if (this.proved && percent >= this.proved * 100 / duration) {
        return;
      }
      this.setBarPosition(percent, 'progressBar');
      this.player.currentTime = percent * duration / 100;
      if (this.isPaused) {
        this.player.style.display = 'block';
        this.player.play();
        this.playTime++;
        this.isPaused = false;
        // this.reportOnOff(1);
      }
    },
    // 拖动进度条
    onBallStart(e) {
      this.isMoveingBall = true;
      const { width } = this.$el.querySelector('.progress-inner').getBoundingClientRect();
      const { pageX } = e.changedTouches[0];
      this.ballPageX = pageX;
      this.progressW = width;
      this.oldBallPercent = this.progressBall;
    },
    onBallMove(e) {
      const { pageX } = e.changedTouches[0];
      this.progressBall = this.getNewPercent(pageX);
    },
    onBallEnd(e) {
      this.isMoveingBall = false;
      const { pageX } = e.changedTouches[0];
      const newPercent = this.getNewPercent(pageX);
      this.setProgressPosition(newPercent);
    },
    // 获取拖动百分比
    getNewPercent(pageX) {
      let newPercent = (pageX - this.ballPageX) * 100 / this.progressW + this.oldBallPercent;
      if (newPercent <= 0) {
        newPercent = 0
      } else if (newPercent >= 100) {
        newPercent = 100
      }
      return newPercent;
    },
    selectRate(rate) {
      if (!this.url) {
        return;
      }
      this.player.playbackRate = rate;
      this.curtRate = rate;
      this.showRate = false;
    },
    formatTime(t) {
      const time = formatLeftTimeObj(t);
      const h = time.h === '00' ? '' : `${time.h}:`;
      return `${h}${time.f}:${time.s}`;
    },
    dealTime(t) {
      let text = '';
      if (t < 60) {
        text = `${t}秒`
      } else {
        let second = t % 60;
        let minute = parseInt(t / 60);
        if (second === 0) {
          text = `${minute}分钟`
        } else {
          text = `${minute}分${second}秒`
        }
      }
      return text;
    },
    // 试看结束
    provedEnd() {
      this.player.pause();
      this.player.currentTime = this.proved;
      if (this.isAndroid) {
        this.player.style.display = 'none';
      }
      if (!this.provedOver) {
        this.$emit('onVideoEnd', { type: 2 });
        this.reportOnOff(2);
        this.reportLeave();
      }
      this.finish = true;
      this.showReplay = true;
      this.provedOver = true;
      this.isFullScreen = false;
    },
    // 播放结束
    onEnded() {
      this.$emit('onVideoEnd', { type: 1 });
      this.finish = true;
      if (this.isAndroid) {
        this.player.style.display = 'none';
      }
      this.reportOnOff(2);
      this.reportLeave();
      this.$nextTick(() => {
        if (this.coverType > 0 && this.coverType !== 13) {
          this.isFullScreen = false;
        }
      })
    },
    onError() {
      if (this.url) {
        this.showError = true
      }
    },
    // 全屏
    onFullscreen() {
      this.isFullScreen = !this.isFullScreen;
    },
    // 上报播放、暂停,status：1开始，2暂停
    reportOnOff(status = 1) {
      const { chapterId, courseId, lectureId } = this.opts;
      if (!chapterId || !courseId || !lectureId) {
        return;
      }
      this.POST('contents/files/resourceRecord', {
        fileType: 1,
        resourceInfo1: courseId,
        resourceInfo2: chapterId,
        resourceInfo3: lectureId,
        resourceType: 1,
        status,
        systemType: 3,
        timestamp: Date.now(),
      })
    },
    // 上报离开
    reportLeave() {
      if (!this.currentTime || !this.duration) {
        return;
      }
      const { chapterId, courseId, lectureId } = this.opts;
      if (!chapterId || !courseId || !lectureId) {
        return;
      }
      this.POST('contents/joinCourse/', {
        requestList: [{
          chapterId,
          courseId,
          lectureId,
          nowTime: this.currentTime,
          time: this.duration,
          timeStamp: Date.now(),
        }],
      })
    },
  },
}
</script>

<style lang="less" scoped>
.pica-video{
  position: relative;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: #333;
  overflow: hidden;
  z-index: 1000;
  video{
    position: absolute;
    left: 50%;
    top: 50%;
    width: 100%;
    max-width: 100%;
    max-height: 100%;
    transform: translate3d(-50%, -50%, 0);
    &::-internal-media-controls-download-button {
      display: none;
    }
    &::-webkit-media-controls-enclosure {
      overflow: hidden;
    }
    &::-webkit-media-controls-panel {
      width: calc(100% + 30px);
    }
  }
  .video-cover{
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
  }
  .control-box{
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 44px;
  }
  .control-bar{
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    left: 0;
    top: 0;
    width: 100%;
    height: 44px;
    // transform: translate3d(0, 60px, 0);
    // transition: transform 0.2s;
    background: linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%);
  }
  .btn-play{
    width: 44px;
    height: 44px;
    background-image: url('~@/images/video/play.png');
    background-repeat: no-repeat;
    background-position: 50% 50%;
    background-size: 24px auto;
  }
  .btn-pause{
    background-image: url('~@/images/video/pause.png');
  }
  .progress-box{
    position: relative;
    display: flex;
    align-items: center;
    flex: 1;
    width: 50px;
    height: 44px;
    margin-left: 5px;
  }
  .progress-inner{
    position: relative;
    width: 50px;
    flex: 1;
    height: 2px;
    background: rgba(255, 255, 255, 0.4);
    overflow: hidden;
  }
  .progress-bar{
    position: absolute;
    left: -100%;
    top: 0;
    width: 100%;
    height: 100%;
    background: #449284;
    transform: translateX(0);
    pointer-events: none;
  }
  .progress-ball{
    position: absolute;
    left: 0;
    top: 50%;
    width: 7px;
    height: 14px;
    transform: translate3d(-3px, -7px, 0);
    background-color: #fff;
    border-radius: 2px;
  }
  .time-box{
    color: #fff;
    font-size: 12px;
    line-height: 14px;
    width: 100px;
    text-align: right;
  }
  .btn-screen{
    width: 44px;
    height: 44px;
    background-image: url('~@/images/video/screen_full.png');
    background-repeat: no-repeat;
    background-position: 50% 50%;
    background-size: 20px auto;
  }
  .btn-screen-mini{
    background-image: url('~@/images/video/screen_mini.png');
  }
  .rate-box{
    position: relative;
    color: #fff;
    width: 40px;
    height: 44px;
    line-height: 44px;
    font-size: 12px;
    text-align: center;
  }
  .rate-list{
    position: absolute;
    left: 0;
    bottom: 44px;
    width: 100%;
    background: rgba(0, 0, 0, .7);
    border-radius: 2px;
  }
  .rate-item{
    height: 30px;
    line-height: 30px;
  }
  .rate-active{
    color: #00a1d6;
  }
  .proved-box{
    position: absolute;
    color: #fff;
    font-size: 12px;
    left: 10px;
    bottom: 30px;
    height: 24px;
    line-height: 24px;
    padding: 0 12px;
    border-radius: 12px;
    background-color: rgba(0, 0, 0, .6);
    span{
      color: #FFA34B;
    }
  }
  .cover-play{
    background: url('~@/images/video/cover_play.png') no-repeat center center;
    background-size: 50px auto;
  }
  .cover-error, .cover-resume{
    p{
      position: absolute;
      left: 0;
      top: 50%;
      width: 100%;
      color: #fff;
      font-size: 15px;
      text-align: center;
      transform: translate3d(0, -50%, 0);
    }
  }
  .replay-box{
    position: absolute;
    color: #fff;
    font-size: 12px;
    right: 10px;
    bottom: 12px;
    height: 24px;
    line-height: 24px;
    padding: 0 12px 0 22px;
    border-radius: 12px;
    background: url('~@/images/video/replay.png') no-repeat left center;
    background-size: 23px auto;
    background-color: rgba(0, 0, 0, .6);
  }
  .cover{
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.8);
  }
  .default-img{
    position: absolute;
    left: 50%;
    top: 50%;
    min-width: 100%;
    min-height: 100%;
    max-width: 100%;
    max-height: 100%;
    transform: translate3d(-50%, -50%, 0);
  }
}
</style>
