<template>
  <div class="custom-sketch-rule">
    <sketch-rule
      v-if="sketchRuleReDraw"
      :thick="thick"
      :scale="scale"
      :width="canvasBox().width"
      :height="canvasBox().height"
      :startX="startX"
      :startY="startY"
      :lines="lines"
      :ratio="1"
    ></sketch-rule>

    <div ref="$app" class="edit-screens" @scroll="handleScroll">
      <div ref="$container" class="edit-screen-container" :style="{ width: width * 2 + 'px' }">
        <div
          ref="refSketchRuleBox"
          class="canvas"
          @mousedown="dragCanvas"
          :style="{ marginLeft: '-' + (canvasBox().width / 2 - 25) + 'px' }"
        >
          <div :style="{ pointerEvents: isPressSpace ? 'none' : 'auto' }">
            <slot></slot>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup name="EditRule">
import { listen } from 'dom-helpers';
import { throttle } from 'lodash-es';
import { SketchRule } from 'vue3-sketch-ruler';
import { ref, reactive, onMounted, toRefs, watch, onUnmounted, computed } from 'vue';
import { useChartEditStore } from '@/store/modules/chart/chartEditStore';
import { useChartLayoutStore } from '@/store/modules/chart/chartLayoutStore';

const chartEditStore = useChartEditStore();
const chartLayoutStore = useChartLayoutStore();

const { width, height } = toRefs(chartEditStore.getEditCanvasConfig);

let prevMoveXValue = [0, 0];
let prevMoveYValue = [0, 0];
const $app = ref();
const sketchRuleReDraw = ref(true);
const refSketchRuleBox = ref();
const $container = ref();
const isPressSpace = ref(false);
const cursorStyle = ref('auto');

const scale = computed(() => {
  return chartEditStore.getEditCanvas.scale;
});

// x轴标尺开始的坐标数值
const startX = ref(0);
// y轴标尺开始的坐标数值
const startY = ref(0);
// 标尺的厚度
const thick = ref(20);
// 初始化水平标尺上的参考线
const lines = reactive({ h: [], v: [] });

const isInit = ref(true);

// 滚动条拖动的高度
const containerWidth = computed(() => {
  return `${height.value * 2}px`;
});

// 处理鼠标拖动
const handleWheel = e => {
  if (e.ctrlKey || e.metaKey) {
    e.preventDefault();
    let resScale = scale.value;
    // 放大(200%)
    if (e.wheelDelta >= 0 && scale.value < 2) {
      resScale = scale.value + 0.05;
      chartEditStore.setScale(resScale);
      return;
    }
    // 缩小(10%)
    if (e.wheelDelta < 0 && scale.value > 0.1) {
      resScale = scale.value - 0.05;
      chartEditStore.setScale(resScale);
    }
  }
};

// 滚动条处理
const handleScroll = () => {
  if (!$app.value) return;
  if (isInit.value) {
    isInit.value = false;
    return;
  }
  const screensRect = $app.value.getBoundingClientRect();
  const canvasRect = refSketchRuleBox.value.getBoundingClientRect();
  // 标尺开始的刻度
  startX.value = (screensRect.left + thick.value - canvasRect.left) / scale.value;
  startY.value = (screensRect.top + thick.value - canvasRect.top) / scale.value;
};

// 拖拽处理
const dragCanvas = e => {
  e.preventDefault();
  e.stopPropagation();

  if (e.which == 2) isPressSpace.value = true;
  else if (!window.$KeyboardActive?.space) return;
  // @ts-ignore
  document.activeElement?.blur();

  const startX = e.pageX;
  const startY = e.pageY;

  const listenMousemove = listen(window, 'mousemove', e => {
    const nx = e.pageX - startX;
    const ny = e.pageY - startY;

    const [prevMoveX1, prevMoveX2] = prevMoveXValue;
    const [prevMoveY1, prevMoveY2] = prevMoveYValue;

    prevMoveXValue = [prevMoveX2, nx];
    prevMoveYValue = [prevMoveY2, ny];

    $app.value.scrollLeft -= prevMoveX2 > prevMoveX1 ? Math.abs(prevMoveX2 - prevMoveX1) : -Math.abs(prevMoveX2 - prevMoveX1);
    $app.value.scrollTop -= prevMoveY2 > prevMoveY1 ? Math.abs(prevMoveY2 - prevMoveY1) : -Math.abs(prevMoveY2 - prevMoveY1);
  });

  const listenMouseup = listen(window, 'mouseup', () => {
    listenMousemove();
    listenMouseup();
    prevMoveXValue = [0, 0];
    prevMoveYValue = [0, 0];
    isPressSpace.value = false;
  });
};

const canvasBox = () => {
  const layoutDom = document.getElementById('custom-chart-edit-layout');
  if (layoutDom) {
    // 此处减去滚动条的宽度和高度
    const scrollW = 20;
    return {
      height: layoutDom.clientHeight - scrollW,
      width: layoutDom.clientWidth - scrollW
    };
  }
  return {
    width: width.value,
    height: height.value
  };
};

// 重绘标尺
const reDraw = () => {
  sketchRuleReDraw.value = false;
  setTimeout(() => {
    sketchRuleReDraw.value = true;
  }, 10);
};

// 滚动居中
const canvasPosCenter = () => {
  const { width: containerWidth, height: containerHeight } = $container.value.getBoundingClientRect();
  const { width, height } = canvasBox();
  $app.value.scrollLeft = containerWidth / 2 - width / 2;
  $app.value.scrollTop = containerHeight / 2 - height / 2;
};

// 处理标尺重制大小
watch(
  () => scale.value,
  (newValue, oldValue) => {
    if (oldValue !== newValue && chartLayoutStore.getRePositionCanvas) {
      chartLayoutStore.setItemUnHandle('rePositionCanvas', false);
      handleScroll();
      setTimeout(() => {
        canvasPosCenter();
        reDraw();
      }, 400);
    } else {
      throttle(reDraw, 20);
    }
  }
);

// 处理鼠标样式
watch(
  () => isPressSpace.value,
  newValue => {
    cursorStyle.value = newValue ? 'grab' : 'auto';
  }
);

onMounted(() => {
  if ($app.value) {
    $app.value.addEventListener('wheel', handleWheel, { passive: false });
    canvasPosCenter();
  }
});

onUnmounted(() => {
  if ($app.value) {
    $app.value.removeEventListener('wheel', handleWheel);
  }
});
</script>

<style>
/* 使用 SCSS 会报错，直接使用最基础的 CSS 进行修改 */

#mb-ruler {
  top: 0;
  left: 0;
}

/* 横线 */
#mb-ruler .v-container .lines .line {
  /* 最大缩放 200% */
  width: 200vw !important;
  border-top: 1px dashed #51d6a9 !important;
}
#mb-ruler .v-container .indicator {
  border-bottom: 1px dashed #51d6a9 !important;
}
/* 竖线 */
#mb-ruler .h-container .lines .line {
  /* 最大缩放 200% */
  height: 200vh !important;
  border-left: 1px dashed #51d6a9 !important;
}
#mb-ruler .h-container .indicator {
  border-left: 1px dashed #51d6a9 !important;
}
/* 坐标数值背景颜色 */
#mb-ruler .indicator .value {
  background-color: #fff;
}
/* 删除按钮 */
#mb-ruler .line .del {
  padding: 0;
  color: #51d6a9;
  font-size: 26px;
  font-weight: bolder;
}

#mb-ruler .corner {
  border-width: 0 !important;
}
</style>

<style scoped lang="less">
.custom-sketch-rule {
  overflow: hidden;
  width: 100%;
  height: 100%;

  .edit-screens {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: auto;
    user-select: none;
    padding-bottom: 0px;
    bottom: 4px;

    /* firefox */
    scrollbar-color: rgba(144, 146, 152, 0.3) transparent;
    scrollbar-width: thin;

    /* chrome */
    &::-webkit-scrollbar,
    &::-webkit-scrollbar-track-piece {
      background-color: transparent;
    }

    &::-webkit-scrollbar {
      width: 7px;
    }

    &::-webkit-scrollbar-thumb {
      border-radius: 5px;
      background-color: rgba(144, 146, 152, 0.3);
    }
    &::-webkit-scrollbar-corner {
      background-color: transparent;
    }
  }

  .fix-edit-screens-block {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 10px;
    height: 10px;
    background-color: #18181c;
  }

  .edit-screen-container {
    position: absolute;
    height: v-bind('containerWidth');
    top: 0;
    left: 0;
  }

  .canvas {
    position: absolute;
    top: 50%;
    left: 50%;
    transform-origin: 50% 0;
    transform: translateY(-50%);

    &:hover {
      cursor: v-bind('cursorStyle');
    }

    &:active {
      cursor: crosshair;
    }
  }
}
</style>
