<template>
  <div
    id="wrapper"
    class="wrapper vue-ruler-wrapper"
    :style="{
      width: width + thick + 'px',
      height: height + thick + 'px'
    }"
  >
    <i
      :class="{
        'iconfont-bigscreen': true,
        'icon-eye': isShowReferLine,
        'icon-eye-close': !isShowReferLine
      }"
      @click="handleCornerClick"
    />
    <SketchRule
      :key="scale"
      :lang="lang"
      :thick="thick"
      :scale="scale"
      :width="width"
      :height="height"
      :start-x="startX"
      :start-y="startY"
      :shadow="shadow"
      :hor-line-arr="[...lines.h, ...presetLines.h]"
      :ver-line-arr="[...lines.v, ...presetLines.v]"
      :palette="Palette"
      :is-show-refer-line="isShowReferLine"
      :corner-active="cornerActive"
      @handleLine="handleLine"
      @onCornerClick="handleCornerClick"
    />
    <div
      id="screens"
      ref="screensRef"
      :style="{
        width: innerWidth + 'px',
        height: innerHeight + 'px'
      }"
      @scroll="throttleScroll"
    >
      <div
        id="screen-container"
        ref="containerRef"
        class="screen-container grid-bg"
        :style="containerRefStyle"
      >
        <div
          id="canvas"
          :style="canvasStyle"
        >
          <slot />
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import SketchRule from 'vue-sketch-ruler'
import { mapState, mapMutations } from 'vuex'
import throttle from 'lodash/throttle'
export default {
  components: {
    SketchRule
  },
  props: {
    width: {
      type: Number,
      default: 500
    },
    height: {
      type: Number,
      default: 400
    },
    pageWidth: {
      type: Number,
      default: 1920
    },
    pageHeight: {
      type: Number,
      default: 1080
    }
  },
  data () {
    return {
      canvasLeft: 0, // 存储画布到视口的left距离
      canvasTop: 0, // 存储画布到视口的top距离
      isDrag: false, // 小地图白块是否拖拽
      startX: 0,
      startY: 0,
      lines: {
        h: [],
        v: []
      },
      thick: 20,
      lang: 'zh-CN', // 中英文
      isShowRuler: true, // 显示标尺
      isShowReferLine: true, // 显示参考线
      cornerActive: true, // 左上角激活状态
      Palette: {
        bgColor: 'rgba(225,225,225, 0)',
        longfgColor: '#BABBBC',
        shortfgColor: '#C8CDD0',
        fontColor: '#7D8694',
        shadowColor: 'transparent',
        lineColor: '#0089d0',
        borderColor: '#transparent',
        cornerActiveColor: 'rgb(235, 86, 72, 0.6)'
      },

      containerRefStyle: {
        width: this.width + 'px',
        height: this.height + 'px'
      },
      innerHeight: 0,
      innerWidth: 0
    }
  },
  watch: {
    // 缩放改变的时候，改变startX，startY
    scale (scale) {
      // 防抖调用方法
      this.throttleScroll()
    },
    pageWidth (pageWidth) {
      if (this.fitZoom === this.zoom) {
        this.initZoom()
      }
    },
    pageHeight (pageHeight) {
      if (this.fitZoom === this.zoom) {
        this.initZoom()
      }
    }
  },
  computed: {
    ...mapState('bigScreen', {
      scale: state => state.zoom / 100,
      fitZoom: state => state.fitZoom,
      zoom: state => state.zoom
    }),
    presetLines () {
      const presetLine = this.$store.state.bigScreen.presetLine
      // { type: 'h', site: y || 0 },
      const v = presetLine?.filter(p => p.type === 'h')?.map(p => p.site)
      const h = presetLine?.filter(p => p.type === 'v')?.map(p => p.site)
      return {
        h,
        v
      }
    },
    shadow () {
      return {
        x: 0,
        y: 0,
        width: this.width,
        height: this.height
      }
    },
    canvasStyle () {
      return {
        width: this.width + 'px',
        height: this.height + 'px',
        transform: `scale(${this.scale})`,
        transformOrigin: '0 0 0'
      }
    }
  },
  mounted () {
    // 初始化canvasLeft canvasTop
    const canvasRect = document.querySelector('#canvas').getBoundingClientRect()
    this.canvasLeft = canvasRect.left
    this.canvasTop = canvasRect.top
    // 监听屏幕改变
    this.listenSize()
    this.initRuleHeight()
    this.throttleScroll()
    this.throttleDrag()
  },
  methods: {
    ...mapMutations('bigScreen', [
      'changeZoom',
      'changeFitZoom'
    ]),
    throttleDrag () {
      throttle(() => {
        this.dragSelection()
        this.viewMapDrag()
      }, 100)()
    },
    // 绑定滑块拖拽效果
    dragSelection () {
      const that = this
      const draggableElement = document.getElementById('selectionWin')
      const dragContainer = document.getElementById('selectWin')
      const screenElement = document.getElementById('screens')
      const screenContainer = document.getElementById('screen-container')
      const maxContainer = document.querySelector('.bs-page-design-wrap')
      // 鼠标按下的位置
      let posX, posY
      // 白色拖拽块相对于父盒子初始位置
      let initialX, initialY
      // 滚动条初始位置
      let scrollTop, scrollLeft
      draggableElement.addEventListener('mousedown', function (event) {
        that.isDrag = true
        posX = event.clientX
        posY = event.clientY
        initialX = draggableElement.getBoundingClientRect().left - dragContainer.getBoundingClientRect().left
        initialY = draggableElement.getBoundingClientRect().top - dragContainer.getBoundingClientRect().top
        scrollLeft = screenElement.scrollLeft
        scrollTop = screenElement.scrollTop
        maxContainer.addEventListener('mousemove', function (event) {
          // 在鼠标移动过程中判断出鼠标左键未点击，则停止拖拽
          if (event.buttons !== 1) {
            that.isDrag = false
          }
          if (that.isDrag) {
            event.preventDefault()
            // 鼠标移动距离
            let moveX = event.clientX - posX
            let moveY = event.clientY - posY
            // 避免白色拖拽移出边框
            if (moveX < -initialX) {
              moveX = -initialX
            } else if (moveX > dragContainer.getBoundingClientRect().width - draggableElement.getBoundingClientRect().width - initialX) {
              moveX = dragContainer.getBoundingClientRect().width - draggableElement.getBoundingClientRect().width - initialX
            }
            if (moveY < -initialY) {
              moveY = -initialY
            } else if (moveY > dragContainer.getBoundingClientRect().height - draggableElement.getBoundingClientRect().height - initialY) {
              moveY = dragContainer.getBoundingClientRect().height - draggableElement.getBoundingClientRect().height - initialY
            }
            const newX = moveX + initialX
            const newY = moveY + initialY
            // 移动拖拽白块
            draggableElement.style.left = newX + 'px'
            draggableElement.style.top = newY + 'px'
            // 移动比例
            const percentageX = moveX / (dragContainer.getBoundingClientRect().width - draggableElement.getBoundingClientRect().width)
            const percentageY = moveY / (dragContainer.getBoundingClientRect().height - draggableElement.getBoundingClientRect().height)
            // 进度条需要滚动的距离
            const scrollTopLength = percentageY * (screenContainer.getBoundingClientRect().height - screenElement.getBoundingClientRect().height)
            const scrollLeftLength = percentageX * (screenContainer.getBoundingClientRect().width - screenElement.getBoundingClientRect().width)
            screenElement.scrollLeft = scrollLeft + scrollLeftLength
            screenElement.scrollTop = scrollTop + scrollTopLength
          }
        })
      })
      maxContainer.addEventListener('mouseup', function (event) {
        that.isDrag = false
      })
      draggableElement.addEventListener('mouseup', function () {
        that.isDrag = false
      })
      // 禁止H5自带的拖拽事件
      draggableElement.ondragstart = function (ev) {
        ev.preventDefault()
      }
      draggableElement.ondragend = function (ev) {
        ev.preventDefault()
      }
      screenElement.ondragstart = function (ev) {
        ev.preventDefault()
      }
      screenElement.ondragend = function (ev) {
        ev.preventDefault()
      }
    },
    // 小地图拖拽
    viewMapDrag () {
      const mapElement = document.getElementById('minimap')
      const mapDragElement = document.getElementById('mapHeader')
      const pageElement = document.querySelector('.bs-page-design-wrap')
      let mapDrag = false
      let curX, curY
      let curBottom, curRight
      mapDragElement.addEventListener('mousedown', function (event) {
        mapDrag = true
        curX = event.clientX
        curY = event.clientY
        curBottom = window.getComputedStyle(mapElement).bottom
        curRight = window.getComputedStyle(mapElement).right
        pageElement.addEventListener('mousemove', function (event) {
          if (mapDrag) {
            event.preventDefault()
            const dragX = event.clientX - curX
            const dragY = event.clientY - curY
            mapElement.style.bottom = parseInt(curBottom) - dragY + 'px'
            mapElement.style.right = parseInt(curRight) - dragX + 'px'
          }
        })
      })
      pageElement.addEventListener('mouseup', function () {
        mapDrag = false
      })
      mapDragElement.addEventListener('mouseup', function () {
        mapDrag = false
      })
    },
    listenSize () {
      window.onresize = throttle(() => {
        this.initRuleHeight()
      }, 100)
    },
    initRuleHeight () {
      setTimeout(() => {
        const screensRect = document
          .querySelector('.grid-wrap-box')
          ?.getBoundingClientRect()
        if (!screensRect) {
          return
        }

        // 30是grid-wrap-box的底部工具栏高度
        this.innerHeight = screensRect.height
        this.innerWidth = screensRect.width
        this.diffX = this.width - screensRect.width
        this.diffY = this.height - screensRect.height

        this.containerRefStyle = {
          width: this.diffX > 0 ? ((this.width + this.diffX + this.thick + 30) + 'px') : (this.width + 'px'),
          height: this.diffY > 0 ? ((this.height + this.diffY + this.thick + 30) + 'px') : (this.height + 'px')
        }
        if (this.fitZoom === this.zoom) {
          this.initZoom()
        }
      })
    },
    handleLine (lines) {
      this.lines = lines
    },
    handleCornerClick () {
      this.isShowReferLine = !this.isShowReferLine
      this.cornerActive = !this.cornerActive
    },
    throttleScroll () {
      throttle(() => {
        this.handleScroll()
      }, 100)()
    },
    handleScroll () {
      const screensRect = document
        .querySelector('#screens')
        .getBoundingClientRect()
      const canvasRect = document
        .querySelector('#canvas')
        .getBoundingClientRect()
      // const container = document.querySelector('#selectWin').getBoundingClientRect()
      const screenContainer = document.querySelector('#screen-container').getBoundingClientRect()
      const draggableElement = document.getElementById('selectionWin')
      // 标尺开始的刻度
      const startX = (screensRect.left + this.thick - canvasRect.left) / this.scale
      const startY = (screensRect.top + this.thick - canvasRect.top) / this.scale

      this.startX = startX >> 0
      this.startY = startY >> 0

      this.$emit('changeStart', {
        x: this.startX * this.scale + 50 - this.thick,
        y: this.startY * this.scale + 50 - this.thick
      })
      // 拖动进度条移动小地图
      if (!this.isDrag) {
        const leftDrag = canvasRect.left - this.canvasLeft
        const topDrag = canvasRect.top - this.canvasTop
        // 小方块需要移动的距离
        const leftLength = leftDrag / (screenContainer.width - screensRect.width - 9) * (150 - 30)
        const topLength = topDrag / (screenContainer.height - screensRect.height - 9) * (150 - 30)
        draggableElement.style.left = -leftLength + 'px'
        draggableElement.style.top = -topLength + 'px'
      }
    },
    // 保证画布能完整展示大屏
    initZoom () {
      // 横向比例
      const xRadio = this.innerWidth / (this.pageWidth + 120)
      // 纵向比例
      const yRadio = this.innerHeight / (this.pageHeight + 120)
      // 取最小的适应比例
      const scale = Math.floor(Math.min(xRadio * 100, yRadio * 100))
      if (scale < 100) {
        this.changeZoom(scale)
        this.changeFitZoom(scale)
      } else {
        this.changeZoom(100)
        this.changeFitZoom(100)
      }
    }
  }
}
</script>
<style lang="scss" scoped>
@import '../../BigScreenDesign/fonts/iconfont.css';
.wrapper {
  box-sizing: border-box;
  position: absolute;

  .iconfont-bigscreen {
    position: absolute;
    left: 0;
    top: 0;
    font-size: 16px;
    color: #fff;
    z-index: 999;
    cursor: pointer;
  }
}

#screens {
  position: absolute;
  overflow: scroll;

  // 滚动条美化，始终在最下方和最右方
  &::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  &::-webkit-scrollbar-thumb {
    border-radius: 10px;
    background-color: var(--bs-el-background-2) !important;
  }
  &::-webkit-scrollbar-track {
    border-radius: 10px;
    background-color: transparent !important;
  }
}

.screen-container {
  position: absolute;
  overflow:hidden;
  width: 6000px;
  height: 6000px;
}

.scale-value {
  position: absolute;
  left: 0;
  bottom: 100%;
}

.button {
  position: absolute;
  left: 100px;
  bottom: 100%;
}

.button-ch {
  position: absolute;
  left: 200px;
  bottom: 100%;
}
.button-en {
  position: absolute;
  left: 230px;
  bottom: 100%;
}

#canvas {
  position: absolute;
  top: 50px;
  left: 50px;
}
::v-deep .line {
  border-left: 1px dashed #0089d0 !important;
  border-top: 1px dashed #0089d0 !important;
}
::v-deep.action {
  .value {
    background: var(--bs-el-color-primary);
    padding: 4px;
    color: #fff;
  }

  .del {
    color: var(--bs-el-color-primary);
  }
}
::v-deep .ruler, ::v-deep .corner {
  background: var(--bs-background-1);
}
::v-deep .corner {
  z-index: 999;
  background: var(--bs-background-1) !important;
}

::v-deep .mb-ruler {
  z-index: 998
}
.grid-bg {
  background-color: #2a2e33 !important;
  background-image: url(./images/canvas-bg.png);
    background-repeat: repeat;
    word-spacing: 10px;
}

::v-deep .lines {
  .line {
    .action {
      .del {
        color: var(--bs-el-text);
      }

      .value {
        color: var(--bs-el-text);
      }
    }
  }
}
</style>
