<template>
  <canvas class="bl___canvas zIndexByJs" :id="id" :canvasId="canvasId"
          :data-zIndex="zIndex"
          :type="type"
          bili-type="canvas"
          :class="{'bl___canvas-opacity': isDowngrade}"
          @touchstart.capture="_eventHandlerTouchstart"
          @touchmove.capture="_eventHandlerTouchmove"
          @touchend.capture="_eventHandlerTouchend"
          @touchcancel.capture="_eventHandlerTouchcancel"
          @longtap.capture="_eventHandlerLongtap"
          @error.capture="_eventHandlerError"
          @onResize="_onResize"
  >
    <slot></slot>
  </canvas>
</template>

<script>
import { judgeEnv, CanvasOnRender, compareVersion, judgeCanvasSync } from './CanvasOnRender'
import ERROR from "../../enum/error";

export default {
  name: 'Bili_Canvas',
  props: {
    "type": {
      type: String,
      default: ''
    },
    "canvasId": {
      type: String,
      default: ''
    },
    "id": {
      type: String,
      default: ''
    },
    "disableScroll": {
      type: Boolean,
      default: false
    },
    "zIndex": {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      observer: null,
      systemInfo: {},
      isDowngrade: false,
      longtapEvent: null,
      isCreate: false
    };
  },
  created() {
    if (judgeEnv().env === 'Service') {
      const pageId = global.__biliCacheData.getCurrentPageId();
      // 处理Service层事件映射
      let eventMapping = {
        touchstart: this._eventHandlerTouchstart,
        touchmove: this._eventHandlerTouchmove,
        touchend: this._eventHandlerTouchend,
        touchcancel: this._eventHandlerTouchcancel,
        longtap: this._eventHandlerLongtap,
        error: this._eventHandlerError,
        resize: this._onResize,
      };
      let event = Object.keys(this.$listeners);
      let eventTemp = {};
      event.forEach(x => {
        eventTemp[x] = eventMapping[x];
      });
      let _readyData = global.canvas[pageId];
      // console.log('-- canvas message[Service]：初始化事件完毕 ok', eventTemp);
      // 判断是否二次销毁重建
      if (_readyData && _readyData[this.id || this.canvasId]) {
        // 用户destroy后再创建
        // console.log('-- canvas message[Service]：destroy后再创建 ok');
        _readyData[this.id || this.canvasId].status = 'init'
        _readyData[this.id || this.canvasId].event = eventTemp
      } else {
        if (!global.canvas) global.canvas = {};
        // 如果相同canvas id  则不处理和渲染，只用第一个。
        if (global.canvas[this.id || this.canvasId]) return;
        // 全局缓存
        global.canvas[this.id || this.canvasId] = {
          id: this.id || this.canvasId,
          queue: [],
          preQueue: [],
          status: 'init',
          event: eventTemp,
          canvas: null,
          ctx: null,
          instance: null,
          isNewCreate: false,
          pageId: '',
          style: {
            fixed: false,
            height: 0,
            hidden: false,
            width: 0,
            x: 0,
            y: 0
          },
          componentId: ''
        };
        // console.log('-- canvas message[Service]：初始化全局参数完毕 ok', global.canvas[this.id || this.canvasId]);
      }
    }
  },
  methods: {
    // eventHadler
    eventHandler(eventName, $event){
      // console.log(eventName, $event)
      if (judgeEnv().isDowngrade) {
        // console.log('降级事件：', this.disableScroll)
        if (this.disableScroll && $event.cancelable) {
          $event.preventDefault();
        }
        if (eventName === 'longtap') {
          Object.defineProperty($event, 'type', {
            value: 'longTap'
          })

        }
        this.$emit(eventName, $event);
      } else {
        const pageId = global.__biliCacheData.getCurrentPageId();
        const offsetLeft = global.canvas[pageId][this.id || this.canvasId].style.x;
        const offsetTop = global.canvas[pageId][this.id || this.canvasId].style.y;
        this.$emit(eventName, Object.assign($event, {target: {
            id: this.id || this.canvasId,
            target: this.id || this.canvasId,
            offsetLeft: offsetLeft,
            offsetTop: offsetTop
          }}));
      }
    },
    // 事件不能在Render层阻断，否则安卓降级方案就将 - 凉凉...
    _eventHandlerTouchstart($event) {
      if (judgeEnv().isDowngrade) {
        // 降级兼容 longtap 长按事件
        if (this.longtapEvent === null) {
          this.longtapEvent = setInterval(()=>{
            this._eventHandlerLongtap($event);
          }, 500)
          // console.log('降级兼容 longtap 长按事件', this.longtapEvent)
        }
      }
      this.eventHandler('touchstart', $event)
    },
    _eventHandlerTouchmove($event) {
      if (judgeEnv().isDowngrade) {
        // 降级兼容 longtap 长按事件
        if (this.longtapEvent !== null) {
          clearInterval(this.longtapEvent);
          this.longtapEvent = setInterval(()=>{
            this._eventHandlerLongtap($event);
          }, 500)
        }
      }

      this.eventHandler('touchmove', $event)
    },
    _eventHandlerTouchend($event) {
      if (judgeEnv().isDowngrade) {
        // 降级兼容 longtap 长按事件
        if (this.longtapEvent !== null) {
          clearInterval(this.longtapEvent);
        }
      }
      this.eventHandler('touchend', $event)
    },
    _eventHandlerTouchcancel($event) {
      if (judgeEnv().isDowngrade) {
        // 降级兼容 longtap 长按事件
        if (this.longtapEvent !== null) {
          clearInterval(this.longtapEvent);
        }
      }

      this.eventHandler('touchcancel', $event)
    },
    _eventHandlerLongtap($event) {
      this.eventHandler('longtap', $event)
    },
    // 现阶段无redner层客户端报错，预留，需要做Service层报错监控
    _eventHandlerError($event) {
      if (judgeEnv().env === 'Service') {
        let _result = judgeCanvasSync(this.type, null, 'all');
        // 写了2期方案，但是版本不支持，报错提示。
        if (_result.canvas_type && (!_result.canvas_version)) {
          this.$emit('error', {
            detail: ERROR.canvas.CANVAS_NEW_NOT_SUPPORT
          });
        }
      } else {
        this.$emit('error', $event);
      }
    },
    _onResize($event){
      this.$emit('resize', $event)
    }
  },
  mounted() {
    // Render层进行样式计算且监控。
    if (judgeEnv().env === 'Render') {
      // 统一计算层级
      SmallApp.computeIndex();
      let temp =  window.bl.getSystemInfoSync();
      if (compareVersion(window.bl.getSystemInfoSync().SDKVersion,'3.18.0') >= 0 ) {
        this.isCreate = true;
        // console.log('-- canvas message[Render]：render样式功能初始化...');
        this.systemInfo = temp;
        const canvasOnRender = new CanvasOnRender(this)
        canvasOnRender.isSame('create')
        canvasOnRender.monitorDom()
        this.observer = canvasOnRender

        // 非2期方案，展示降级标识
        if (!judgeCanvasSync(this.type, temp)) {
          // 安卓降级需要展示占位符
          if (judgeEnv().isDowngrade) {
            this.isDowngrade = true;
          }
        }
      }
    } else {
      // service层进行判断
      this._eventHandlerError();
    }
  },
  beforeDestroy() {
    // console.log('-- canvas message：进入canvas销毁...');
    // Render层销毁监听, 判断canvas已经创建再做后面操作
    if (judgeEnv().env === 'Render') {
      if (this.isCreate) {
        // render 层销毁监听
        this.observer.disconnect()
        this.observer = null
        // console.log('-- canvas message[Render]：销毁监听 ok');
      }
    } else {
      const pageId = global.__biliCacheData.getCurrentPageId();
      if (global.canvas[pageId] && global.canvas[pageId][this.id || this.canvasId] && global.canvas[pageId][this.id || this.canvasId].canvas) {
        if (!judgeEnv().isDowngrade) {
          // 执行NA销毁canvas方法
          global.canvas[pageId][this.id || this.canvasId].canvas.destroy();
          // console.log('-- canvas message[Service]：通知NA销毁在屏canvas ok');
        }
        // 全局对象重置
        global.canvas[pageId][this.id || this.canvasId].status = 'destroy';
        global.canvas[pageId][this.id || this.canvasId].canvas = null;
        global.canvas[pageId][this.id || this.canvasId].ctx = null;
        global.canvas[pageId][this.id || this.canvasId].componentId = null;
        global.canvas[pageId][this.id || this.canvasId].event = null;
      }
    }
  }
};
</script>

<style lang="less">
.bl___canvas {
  width: 300px;
  height: 150px;
  opacity: 0;
}

.bl___canvas-opacity{
  opacity: 1;
  background-color: white;
  z-index: 1;
}
</style>
