<template>
  <div class="bl___video zIndexByJs"
       :data-zIndex="zIndex"
       :id="id"
       bili-type="video"
       :class="{'full-screen-video': fullScreenVideo}"
       :bili-id="biliId"
  >
    <slot></slot>
  </div>
</template>

<script>
import videoManager from './video-manager';
import {judgeEnv} from '../util/logic';

let focus = null;

export default {
  name: 'Bili_Video',
  props: {
    "id": {
      type: String,
      default: ''
    },
    "src": {
      type: String,
      default: ''
    },
    "controls": {
      type: Boolean,
      default: true
    },
    "danmuBtn": {
      type: Boolean,
      default: false
    },
    "enableDanmu": {
      type: Boolean,
      default: false
    },
    "enableAutoRotation": {
      type: Boolean,
      default: false
    },
    "freeFlowType": {
      type: Number,
      default: 0
    },
    "autoplay": {
      type: Boolean,
      default: false
    },
    "zIndex": {
      type: Number,
      default: 0
    },
    "loop": {
      type: Boolean,
      default: false
    },
    "title": {
      type: String,
      default: ''
    },
    "direction": {
      type: Number,
      default: -1
    },
    "showFullscreenBtn": {
      type: Boolean,
      default: true
    },
    "muted": {
      type: Boolean,
      default: false
    },
    "initialTime": {
      type: Number,
      default: 0
    },
    "enableProgressGesture": {
      type: Boolean,
      default: true
    },
    "playBtnPosition": {
      type: String,
      default: 'bottom'
    },
    "objectFit": {
      type: String,
      default: 'contain'
    },
    "showMuteBtn": {
      type: Boolean,
      default: false
    },
    "enablePlayGesture": {
      type: Boolean,
      default: false
    },
    "vslideGesture": {
      type: Boolean,
      default: false
    },
    "sharedId": {
      type: String,
      default: ''
    },
    "enableAccurateSeek": {
      type: Boolean,
      default: false
    }
  },
  // 监控属性变化
  watch: {
    src: function (value) {
      this.changeAttribute('src', value);
    },
    controls: function (value) {
      this.changeAttribute('controls', value);
    },
    title: function (value) {
      this.changeAttribute('title', value);
    },
    direction: function (value) {
      this.changeAttribute('direction', value);
    },
    showFullscreenBtn: function (value) {
      this.changeAttribute('showFullscreenBtn', value);
    },
    enableAutoRotation: function (value) {
      this.changeAttribute('enableAutoRotation', value);
    },
    enableDanmu: function (value) {
      this.changeAttribute('enableDanmu', value);
    },
    autoplay: function (value) {
      this.changeAttribute('autoplay', value);
    },
    loop: function (value) {
      this.changeAttribute('loop', value);
    },
    muted: function (value) {
      this.changeAttribute('muted', value);
    },
    initialTime: function (value) {
      this.changeAttribute('initialTime', value);
    },
    enableProgressGesture: function (value) {
      this.changeAttribute('enableProgressGesture', value);
    },
    playBtnPosition: function (value) {
      this.changeAttribute('playBtnPosition', value);
    },
    objectFit: function (value) {
      this.changeAttribute('objectFit', value);
    },
    enablePlayGesture: function (value) {
      this.changeAttribute('enablePlayGesture', value);
    },
    vslideGesture: function (value) {
      this.changeAttribute('vslideGesture', value);
    },
  },
  data() {
    return {
      videoInstance: null,
      focus: false,
      observer: null,
      fullScreenVideo: false,
      systemInfo: null,
      biliId: '',
      isHasPre: false,
      cacheMsg: null
    };
  },
  created() {
    let _env = judgeEnv().env;
    this.biliId = this._uid;
    if (_env === 'Service') {
      if (!global.__biliComponentData.video) global.__biliComponentData.video = {};
      const pageId = global.__biliCacheData.getCurrentPageId();
      if (!global.__biliComponentData.video[pageId]) global.__biliComponentData.video[pageId] = {};
      if (!global.__biliComponentData.video[pageId].mapping) global.__biliComponentData.video[pageId].mapping = {};
      if (this.id) global.__biliComponentData.video[pageId].mapping[this.id] = this._uid;
    }
  },
  mounted() {
    let _env = judgeEnv().env;
    if (_env === 'Render') {
      this.systemInfo = bl.getSystemInfoSync();
      SmallApp.computeIndex();
      this.videoInstance = videoManager.register(this.id || this.$attrs.id, this, {
        "src": this.src,
        "controls": this.controls,
        "danmuBtn": this.danmuBtn,
        "enableDanmu": this.enableDanmu,
        "autoplay": this.autoplay,
        "title": this.title,
        "direction": this.direction,
        // "direction": is.Number(this.direction) ? this.direction : -1,
        "showFullscreenBtn": this.showFullscreenBtn,
        "enableAutoRotation": this.enableAutoRotation,
        "freeFlowType": this.freeFlowType,
        "loop": this.loop,
        "muted": this.muted,
        "initialTime": this.initialTime,
        "enableProgressGesture": this.enableProgressGesture,
        "playBtnPosition": this.playBtnPosition,
        "objectFit": this.objectFit,
        "showMuteBtn": this.showMuteBtn,
        "enablePlayGesture": this.enablePlayGesture,
        "vslideGesture": this.vslideGesture,
        "sharedId": this.sharedId,
        "enableAccurateSeek": this.enableAccurateSeek
      });

      if (this.autoplay && focus === null) {
        focus = this;

        this.play('isFirst');
      }
    }
  },
  beforeDestroy() {
    let _env = judgeEnv().env;
    if (_env === 'Render') {
      if (this.doIHaveFocus()) {
        // 将全屏隐藏的NA组件显示出来
        this.changeOtherComponentHide(false);
        this.videoInstance.destroy();
        this.videoInstance = null;
        focus = null;
      }
      videoManager.unRegister(this.id || this.$attrs.id);
    } else {
      // 删除映射
      const pageId = global.__biliCacheData.getCurrentPageId();
      delete global.__biliComponentData.video[pageId].mapping[this.id];
    }

    // 同步销毁组件
    // this.destroyComponent()
  },
  methods: {
    doIHaveFocus() {
      return focus === this;
    },
    play(isFirst) {
      SmallApp.waitStyleOver().then(() => {
        if (!this.doIHaveFocus()) {
          focus && focus.videoInstance && focus.videoInstance.destroy();

          focus = this;
        }

        setTimeout(() => {
          // 确保video destroy成功后再去创建新video，不然会出现新video创建失败，导致无法播放的问题
          this.watchStyle();
          this.videoInstance.create();
          if (!(isFirst === 'isFirst' && this.autoplay)) {
            this.videoInstance.play();
          }
        }, 100);
      });
    },
    pause() {
      if (!this.doIHaveFocus()) {
        return;
      }

      this.videoInstance.pause();
    },
    stop() {
      if (!this.doIHaveFocus()) {
        return;
      }

      this.videoInstance.stop();
    },
    seek({position}) {
      if (!this.doIHaveFocus()) {
        return;
      }

      this.videoInstance.seek(position);
    },
    playbackRate({rate}) {
      if (!this.doIHaveFocus()) {
        return;
      }

      this.videoInstance.setPlaybackRate(rate);
    },
    // handleMessage，作为事件的触发，该方法NA会直接调用。
    handleMessage(message) {
      if (message.type === 'native-component') {
        // 判断客户端前后2次消息是否一致，如果一致的话则过滤掉
        if (this.cacheMsg === null) {
          this.cacheMsg = message;
        } else {
          if (JSON.stringify(this.cacheMsg) !== JSON.stringify(message)) {
            this.cacheMsg = message;
          } else {
            return;
          }
        }
        // 兜底ios历史版本，fullscreenchange在fullscreenchangepre之前错误，ios 6.42之前。
        if (!this.isHasPre && message.event.type === 'fullscreenchangepre') {
          this.isHasPre = true;
          this.changeOtherComponentHide(true);
          return;
        }
        // video增加全屏样式
        if (message.event.type === 'fullscreenchange') {
          let isFullScreen = message.event.detail.fullScreen;
          // 如果状态正在全屏，且下一个消息告诉要退出全屏，则将pre消息重置
          if (this.fullScreenVideo && !isFullScreen) {
            this.isHasPre = false
          }
          this.fullScreenVideo = isFullScreen;
          if (!isFullScreen) {
            this.changeOtherComponentHide(isFullScreen);
          }
        }
        this.$emit(message.event.type, message.event);
      }
    },
    changeOtherComponentHide(isFullScreen) {
      let allCom = [];
      let _zIndexByJsAll = global.document.querySelectorAll('.zIndexByJs');
      for (let _key in _zIndexByJsAll) {
        if (_zIndexByJsAll.hasOwnProperty(_key)) allCom.push(_zIndexByJsAll[_key])
      }
      allCom = allCom.filter(x => {
        return typeof x !== 'number';
      });

      let videoComHas = [];
      let _zIndexByJsVideo = this.$el.querySelectorAll('.zIndexByJs');
      for (let _keySon in _zIndexByJsVideo) {
        if (_zIndexByJsVideo.hasOwnProperty(_keySon)) videoComHas.push(_zIndexByJsVideo[_keySon])
      }
      videoComHas = videoComHas.filter(x => {
        return typeof x !== 'number';
      });

      videoComHas.map(x => {
        if (this.systemInfo.platform.toLowerCase() === 'android') {
          if (isFullScreen) {
            x.style.position = 'fixed';
          } else {
            x.style.position = '';
          };
        }

        let _i = allCom.indexOf(x);
        if (_i > -1) {
          allCom.splice(_i, 1);
        }
      });

      // 设置样式
      allCom.map(x => {
        if (x !== this.$el) {
          let currentStyle = getComputedStyle(x).display;
          if (isFullScreen) {
            x.cacheDisplay = currentStyle;
            x.style.display = 'none';
          } else {
            if (currentStyle === 'none') {
              x.style.display = x.cacheDisplay;
            }
          }
        }
      });
    },
    // 改变属性，且通知Native
    changeAttribute(attrKey, attrValue) {
      // render层执行
      if (judgeEnv().env === 'Render') {
        this.videoInstance.updateAttr(attrKey, attrValue, this.doIHaveFocus());
      }
    },
    // 监控整个body变化，重新计算样式
    watchStyle() {
      if (!this.doIHaveFocus()) {
        this.disconnectObserver();

        return;
      }

      const that = this;
      // 监控整个body变化，如有变化则重新计算样式是否有变动。做节流优化。
      this.observer = new MutationObserver(() => {
        if (!that.doIHaveFocus()) {
          that.disconnectObserver();

          return;
        }

        SmallApp.waitStyleOver().then(() => {
          that.videoInstance.updateStyles();
        });
      });

      this.observer.observe(document.body, {
        attributes: true,
        childList: true,
        characterData: true,
        subtree: true
      });
    },
    disconnectObserver() {
      this.observer && this.observer.disconnect();
      this.observer = null;
    }
  },

};
</script>

<style lang="less">
.bl___video {
  width: 300px;
  height: 225px;
}

.full-screen-video {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: 100% !important;
}
</style>
