<template>
  <div v-if="hasPermission">
    <!-- 控制按钮 -->
    <div class="controls" v-if="pageConfig.fitMode=='cover'">
      <button @click="zoomIn">放大</button>
      <button @click="zoomOut">缩小</button>
      <button @click="zoomEnd">归零</button>
    </div>
    <!-- 画布区域 -->
    <div v-loading="pageLoading" element-loading-background="#151A26" class="bs-preview-wrap" :style="previewWrapStyle">
      <div class="canvas" :style="canvasStyle" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp"
        @mouseleave="onMouseUp" @wheel="onWheel">

        <div class="bs-render-wrap render-theme-wrap" :style="renderStyle">
          <div v-for="chart in chartList" :key="chart.code" :style="getStyle(chart)">
            <Configuration :config="chart" @openDataViewDialog="openDataViewDialog">
              <RenderCard ref="RenderCardRef" :key="chart.key" :config="chart" @styleHandler="styleHandler" />
            </Configuration>
          </div>
        </div>
      </div>
    </div>


    <data-view-dialog ref="dataViewDialog" />
  </div>

  <NotPermission v-else />

</template>
<script>

import RenderCard from 'data-room-ui/Render/RenderCard.vue'
import { mapActions, mapMutations, mapState } from 'vuex'
import { compile } from 'tiny-sass-compiler/dist/tiny-sass-compiler.esm-browser.prod.js'
import NotPermission from 'data-room-ui/NotPermission'
import Configuration from 'data-room-ui/Render/Configuration.vue'
import DataViewDialog from 'data-room-ui/BigScreenDesign/DataViewDialog/index.vue'
import { getFileUrl } from 'data-room-ui/js/utils/file'
import cloneDeep from 'lodash/cloneDeep'
export default {
  name: 'BigScreenRun',
  components: {
    DataViewDialog,
    Configuration,
    RenderCard,
    NotPermission
  },
  props: {
    config: {
      type: Object,
      default: () => ({
        code: '',
        fitSelector: '.inner-preview-wrap',
        fitMode: 'auto'
      })
    }
  },
  data() {
    return {
      innerHeight: window.innerHeight,
      innerWidth: window.innerWidth,
      timer: null,
      hasPermission: true,
      initChartList: [],

      scale: 1, // 缩放比例
      translateX: 0, // 水平位移
      translateY: 0, // 垂直位移
      isDragging: false, // 是否正在拖拽
      startX: 0, // 拖拽起始 X 坐标
      startY: 0 // 拖拽起始 Y 坐标
    }
  },
  computed: {
    // 画布样式
    canvasStyle() {
      return {
        // backgroundColor: this.fitPageConfig.customTheme === 'light' ? this.fitPageConfig.lightBgColor : this.fitPageConfig.bgColor,
        transform: `scale(${this.scale}) translate(${this.translateX}px, ${this.translateY}px)`,
        transformOrigin: '0 0'
      };
    },
    ...mapState({
      pageInfo: state => state.bigScreen.pageInfo,
      pageConfig: state => state.bigScreen.pageInfo.pageConfig,
      chartList: state => state.bigScreen.pageInfo.chartList,
      stateFitMode: state => state.bigScreen.pageInfo.pageConfig.fitMode
    }),
    pageCode() {
      // 内部系统取到外部iframe上src链接的code参数
      const iframeCode = this.getIframeCode()
      // 兼容外部网页上的code,iframe上的code以及传入的code
      return this.$route.query.code ||
        iframeCode ||
        this.config.code
    },
    fitMode() {
      return this.config.fitMode || this.stateFitMode
    },
    fitSelector() {
      return this.config.fitSelector
    },
    pageLoading() {
      return this.$store.state.bigScreen.pageLoading
    },
    fitPageConfig() {
      return this.resolvePageConfig(this.pageConfig)
    },
    previewWrapStyle() {
      const bg = this.fitMode !== 'none'
        ? {
          backgroundColor: this.fitPageConfig.customTheme === 'light' ? this.fitPageConfig.lightBgColor : this.fitPageConfig.bgColor,
          backgroundImage: this.fitPageConfig.customTheme === 'light' ? `url(${this.getCoverPicture(this.fitPageConfig.lightBg)})` : `url(${this.getCoverPicture(this.fitPageConfig.bg)})`,
          backgroundSize: 'cover'
        }
        : {}

      return {
        overflowX: `${this.fitPageConfig.overflowX}`,
        overflowY: `${this.fitPageConfig.overflowY}`,
        ...bg
      }
    },
    renderStyle() {
      const style = {
        width: this.fitPageConfig.w,
        height: this.fitPageConfig.h,
        transform: `scaleX(${this.fitPageConfig.scaleX}) scaleY(${this.fitPageConfig.scaleY}) translate(${this.fitPageConfig.translate})`
      }

      const bg = this.fitMode === 'none'
        ? {
          backgroundColor: this.fitPageConfig.customTheme === 'light' ? this.fitPageConfig.lightBgColor : this.fitPageConfig.bgColor,
          backgroundImage: this.fitPageConfig.customTheme === 'light' ? `url(${this.getCoverPicture(this.fitPageConfig.lightBg)})` : `url(${this.getCoverPicture(this.fitPageConfig.bg)})`,
          backgroundSize: 'cover'
        }
        : {}
      return {
        ...style,
        ...bg
      }
    }
  },
  watch: {
    pageCode(val) {
      if (val) {
        this.init()
      }
    },
    'pageInfo.pageConfig.refreshConfig.length': {
      handler(val) {
        if (val) {
          this.startTimer()
        }
      }
    },
    chartList: {
      handler(val) {
        if (this.initChartList.length === 0) {
          this.initChartList = cloneDeep(this.chartList)
        }
      },
      deep: true
    }
  },
  beforeRouteLeave(to, from, next) {
    // 离开的时候 重置大屏的vuex store
    this.$store.commit('bigScreen/resetStoreData')
    next()
  },
  created() {
    this.permission()
    this.getParentWH()
    this.windowSize()
  },
  mounted() {
    if (this.pageInfo.pageConfig.refreshConfig && this.pageInfo.pageConfig.refreshConfig.length > 0) {
      this.startTimer()
    }
  },
  beforeDestroy() {
    this.stopTimer()
  },
  methods: {
    // 放大
    zoomIn() {
      this.scale += 0.1;
    },
    // 缩小
    zoomOut() {
      if (this.scale > 0.1) {
        this.scale -= 0.1;
      }
    },
    zoomEnd() {
      this.scale = 1
      this.translateX = 0
      this.translateY = 0
    },
    // 鼠标按下
    onMouseDown(event) {
      if(this.pageConfig.fitMode!='cover') return
      this.isDragging = true;
      this.startX = event.clientX - this.translateX;
      this.startY = event.clientY - this.translateY;
    },
    // 鼠标移动
    onMouseMove(event) {
      if(this.pageConfig.fitMode!='cover') return
      if (this.isDragging) {
        this.translateX = event.clientX - this.startX;
        this.translateY = event.clientY - this.startY;
      }
    },
    // 鼠标松开
    onMouseUp() {
      if(this.pageConfig.fitMode!='cover') return
      this.isDragging = false;
    },
    // 鼠标滚轮事件
    onWheel(event) {
      if(this.pageConfig.fitMode!='cover') return
      // 判断是否按下了 Ctrl 键
      if (event.ctrlKey) {
        event.preventDefault(); // 阻止默认行为
        const delta = event.deltaY < 0 ? 0.1 : -0.1; // 根据滚轮方向调整缩放比例
        this.scale += delta;

        // 限制缩放范围
        if (this.scale < 0.1) {
          this.scale = 0.1;
        } else if (this.scale > 5) {
          this.scale = 5;
        }
      }
    },
    ...mapActions('bigScreen', [
      'initLayout' // -> this.initLayout()
    ]),
    ...mapMutations('bigScreen', [
      'changeLayout',
      'changePageLoading',
      'changePageConfig',
      'changeChartConfig'
    ]),
    getStyle(chart) {
      if (chart.perspective > 0) {
        return {
          position: 'absolute',
          width: chart.w + 'px',
          height: chart.h + 'px',
          left: chart.x + 'px',
          top: chart.y + 'px',
          transform: `perspective(${chart.perspective}px) skew(${chart.skewX}deg, ${chart.skewY}deg) rotateX(${chart.rotateX}deg) rotateY(${chart.rotateY}deg)  rotateZ(${chart.rotateZ}deg)`,
          zIndex: chart.z || 0
        }
      }
      return {
        position: 'absolute',
        width: chart.w + 'px',
        height: chart.h + 'px',
        left: chart.x + 'px',
        top: chart.y + 'px',
        transform: `skew(${chart.skewX}deg, ${chart.skewY}deg) rotateX(${chart.rotateX}deg) rotateY(${chart.rotateY}deg)  rotateZ(${chart.rotateZ}deg)`,
        zIndex: chart.z || 0
      }
    },
    // 右键点击查看数据
    openDataViewDialog(config) {
      this.$refs.dataViewDialog.init(config)
    },
    // 切换主题时针对远程组件触发样式修改的方法
    styleHandler(config) {
      this.chartList.forEach((chart, index) => {
        if (chart.code === config.code) {
          this.$refs.RenderCardRef[index].$refs[chart.code].changeStyle(config)
        }
      })
    },
    permission() {
      // this.$dataRoomAxios.get(`/bigScreen/permission/check/${this.pageCode}`).then(res => {
        this.hasPermission = true
        // if (res) {
          this.init()
        // }
      // })
    },
    init() {
      if (!this.pageCode) { return }
      this.changePageLoading(true)
      this.initLayout(this.pageCode).then(() => {
        this.changePageLoading(false)
        this.getParentWH()
      })
    },
    // 设置定时器
    startTimer() {
      console.log('开始刷新')
      let time = 1
      const that = this
      // 使用setTimeout代替setInterval，并在每次循环结束后重新设置定时器。这样可以避免定时器的堆积和性能问题
      // 同时，为了方便清除定时器，可以将定时器的引用保存在变量中，以便后续清除
      this.timer = setTimeout(function refresh() {
        // console.log('that.pageInfo: ', that.pageInfo);
        that.pageInfo.pageConfig.refreshConfig.forEach(item => {
          if (item.code) {
            if (time === 1) {
              item.originTime = item.time
            }
            console.log('that.chartList: ', that.chartList);

            that.chartList.forEach((chart, index) => {
              if (item.code === chart.code && item.time === time) {
                item.time = item.time + item.originTime
                if (that.$refs.RenderCardRef[index].$refs[chart.code]?.componentInstance) {
                  that.$refs.RenderCardRef[index].$refs[chart.code].componentInstance.changeData(chart)
                } else {
                  that.$refs.RenderCardRef[index].$refs[chart.code].changeData(chart)
                }
              }
            })
          }
        })
        time += 1
        that.timer = setTimeout(refresh, 1000)
      }, 1000)
    },
    // 清除定时器
    stopTimer() {
      clearTimeout(this.timer)
    },
    getIframeCode() {
      // 获取当前页面的URL
      const url = window.location.href

      // 解析URL的参数
      let code = null
      // 检查URL中是否包含哈希值
      if (url.indexOf('#') !== -1) {
        // 获取哈希部分的URL
        const hashUrl = url.split('#')[1]
        // 解析哈希部分URL的参数
        const hashParams = new URLSearchParams(hashUrl)
        code = hashParams.get('code')
      } else {
        // 获取URL的查询字符串部分
        const searchParams = new URLSearchParams(url.split('?')[1])
        code = searchParams.get('code')
      }
      return code
    },
    windowSize() {
      window.onresize = () => {
        this.getParentWH()
      }
    },
    getParentWH() {
      this.$nextTick(() => {
        const parent = document.querySelector(this.fitSelector)
        // 如果设置了自适应的选择器
        if (parent) {
          this.innerHeight = parent.offsetHeight
          this.innerWidth = parent.offsetWidth
        } else {
          this.innerHeight = window.innerHeight
          this.innerWidth = window.innerWidth
        }
        // 设置bs-preview-wrap的高度为父元素的高度
        const previewWrap = document.querySelector('.bs-preview-wrap')
        if (previewWrap) {
          previewWrap.style.height = this.innerHeight + 'px'
          previewWrap.style.width = this.innerWidth + 'px'
        }
      })
    },
    // 获取到后端传来的主题样式并进行修改
    styleSet() {
      const style = document.createElement('style')
      if (this.pageConfig.themeJson && this.pageConfig.themeJson.themeCss) {
        const styleStr = this.pageConfig.themeJson.themeCss
        const themeCss = compile(styleStr).code
        style.type = 'text/css'
        style.innerText = themeCss
        document.getElementsByTagName('head')[0].appendChild(style)
      } else {
        style.remove()
      }
    },
    // 处理自适应下的页面配置
    resolvePageConfig(pageConfig) {
      const { w, h } = pageConfig
      let scaleX = 1
      let scaleY = 1
      let translate = '0px, 0px'
      let overflowX = 'auto'
      let overflowY = 'auto'
      // 自适应模式, 画布等比例自适应后保持一屏展示，会存在某一个方向两边留白，留白部分颜色背景和画布中的背景色一致
      if (pageConfig.fitMode === 'auto') {
        const scaleW = this.innerWidth / w
        const scaleH = this.innerHeight / h
        scaleX = Math.min(scaleW, scaleH)
        scaleY = Math.min(scaleW, scaleH)
        translate = `${((this.innerWidth - w) / 2) / scaleX}px, ${((this.innerHeight - h) / 2) / scaleY}px`
        overflowX = 'hidden'
        overflowY = 'hidden'
      }

      // 宽度铺满 预览时画布横向铺满，纵向超出时出现滚动条
      if (pageConfig.fitMode === 'fitWidth') {
        scaleX = this.innerWidth / w
        // 如果实际高度小于屏幕，纵向居中
        if (this.innerHeight > h) {
          translate = `${((this.innerWidth - w) / 2) / scaleX}px, ${((this.innerHeight - h) / 2) / scaleY}px`
        } else {
          translate = `${((this.innerWidth - w) / 2) / scaleX}px, 0px`
        }
        overflowX = 'hidden'
      }

      // 高度铺满 预览时画布纵向铺满，横向超出时出现滚动条
      if (pageConfig.fitMode === 'fitHeight') {
        scaleY = this.innerHeight / h
        // 如果实际宽度小于屏幕，横向居中
        if (this.innerWidth > w) {
          translate = `${((this.innerWidth - w) / 2) / scaleX}px, ${((this.innerHeight - h) / 2) / scaleY}px`
        } else {
          translate = `0px, ${((this.innerHeight - h) / 2) / scaleY}px`
        }
        overflowY = 'hidden'
      }

      // 双向铺满 预览时画布横向纵向铺满，无滚动条，但是元素可能会出现拉伸情况
      if (pageConfig.fitMode === 'cover') {
        scaleX = this.innerWidth / w
        scaleY = this.innerHeight / h
        translate = `${((this.innerWidth - w) / 2) / scaleX}px, ${((this.innerHeight - h) / 2) / scaleY}px`
        overflowX = 'hidden'
        overflowY = 'hidden'
      }

      // 无
      const newPageConfig = {
        ...pageConfig,
        w: w + 'px',
        h: h + 'px',
        scaleX,
        scaleY,
        translate,
        overflowX,
        overflowY
      }

      return newPageConfig
    },
    /**
     * 获取图片访问地址,如果是相对路径则拼接上文件访问前缀地址
     * @param url
     * @returns {*}
     */
    getCoverPicture(url) {
      return getFileUrl(url)
    }
  }
}
</script>

<style lang="scss" scoped>
.bs-preview-wrap {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: auto;

  .bs-render-wrap {
    position: relative;
    background-size: cover;
  }

}

.controls {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 1000000000;
}

button {
  margin: 5px;
  padding: 10px 20px;
  background-color: #42b983;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

button:hover {
  background-color: #3aa876;
}
</style>
