<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const wRuleRef = ref(null)
const props = defineProps({
  tickLabelFormatter: {
    type: Function,
    default: value => value.toString() // 刻度标签格式化函数,默认直接转为字符串
  },
  size: {
    type: Number,
    default: 300 // 尺子方向
  },
  direction: {
    type: String,
    default: 'horizontal' // 尺子方向
  }
})

const labelInterval = 5
const emits = defineEmits(['update:tickSize'])

const { canvasStyleData, curComponent, componentData } = storeToRefs(dvMainStore)

const rulerSize = computed(() =>
  props.direction === 'horizontal' ? canvasStyleData.value.width : canvasStyleData.value.height
)

// 计算复合画布内部组件偏移量
const parentStyle = computed(() => {
  const style = { left: 0, top: 0 }
  if (curComponent.value && curComponent.value.canvasId !== 'canvas-main') {
    componentData.value.forEach(item => {
      if (curComponent.value.canvasId.indexOf(item.id) > -1) {
        style.left = item.style.left
        style.top = item.style.top
      }
    })
    // tab页头部偏移量
    if (curComponent.value.canvasId.indexOf('Group') === -1) {
      style.top = style.top + 56
    }
  }
  return style
})

const curComponentShadow = computed(() => {
  if (curComponent.value) {
    return {
      left:
        (props.direction === 'horizontal'
          ? curComponent.value.style.left + parentStyle.value.left
          : curComponent.value.style.top + parentStyle.value.top) + 'px',
      width:
        (props.direction === 'horizontal'
          ? curComponent.value.style.width
          : curComponent.value.style.height) + 'px'
    }
  } else {
    return {}
  }
})

const ticks = computed(() => {
  const result = []
  let currentValue = 0
  while (currentValue <= rulerSize.value) {
    const isLong = currentValue % (labelInterval * tickSize.value) === 0
    const label = isLong ? props.tickLabelFormatter(currentValue) : ''
    result.push({ position: (currentValue * canvasStyleData.value.scale) / 100, label, isLong })
    currentValue += tickSize.value
  }
  return result
})

const wStyle = computed(() => {
  return {
    width: rulerSize.value * 1.5 + 'px'
  }
})

const radio = computed(() => rulerSize.value / canvasStyleData.value.width)
const tickSize = computed(
  () =>
    10 *
    Math.max(
      Math.floor((200000 * radio.value) / (rulerSize.value * canvasStyleData.value.scale)),
      1
    )
)

const scaleWidth = computed(() => (rulerSize.value * canvasStyleData.value.scale) / 100)

const rulerScroll = e => {
  const left = props.direction === 'vertical' ? e.scrollTop : e.scrollLeft
  wRuleRef.value.scrollTo(left, 0)
}

const outerStyle = computed(() => {
  return {
    width: props.direction === 'vertical' ? props.size - 30 + 'px' : '100%'
  }
})

const curShadowShow = computed(() => curComponent.value && curComponent.value.category !== 'hidden')

const tickSizeScale = computed(() => (tickSize.value * canvasStyleData.value.scale) / 100)

watch(
  () => tickSizeScale.value,
  () => {
    emits('update:tickSize', tickSizeScale.value)
  },
  { immediate: true }
)

defineExpose({
  rulerScroll
})
</script>

<template>
  <div
    class="ruler-outer"
    :style="outerStyle"
    :class="{ 'ruler-vertical': direction === 'vertical' }"
    ref="wRuleRef"
  >
    <!--覆盖着尺子上方防止鼠标移到尺子位置滑动-->
    <div class="ruler-shadow" :style="outerStyle"></div>
    <div :style="wStyle" class="ruler-outer-scroll">
      <div class="ruler" :style="{ width: `${scaleWidth}px` }">
        <div v-if="curShadowShow" :style="curComponentShadow" class="cur-shadow"></div>
        <div class="ruler-line" :style="{ width: `${scaleWidth}px` }"></div>
        <div
          v-for="(tick, index) in ticks"
          :key="index"
          class="ruler-tick"
          :class="{ 'long-tick': tick.isLong }"
          :style="{ left: `${tick.position}px` }"
        >
          <span v-if="tick.isLong" class="tick-label">{{ tick.label }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="less">
.ruler-vertical {
  position: absolute;
  left: 30px;
  top: 30px;
  transform-origin: top left;
  transform: rotate(90deg);
  overflow-y: auto;
  overflow-x: hidden;
  z-index: 2;
  .ruler {
    .ruler-line {
      top: 0;
    }
    .ruler-tick {
      top: 0;
      .tick-label {
        transform: rotate(180deg);
      }
    }
  }
}

.ruler-shadow {
  position: absolute;
  height: 30px;
  z-index: 10;
  overflow: hidden;
}

.ruler-outer {
  overflow-x: auto;
  background-color: #2c2c2c;
  &::-webkit-scrollbar {
    width: 0 !important;
    height: 0 !important;
  }
}

.ruler-outer-scroll {
  min-width: 1600px;
  display: flex;
  justify-content: center;
}
.ruler {
  position: relative;
  height: 30px;
  display: flex;
  align-items: center;
  background-color: #2c2c2c;
}

.ruler-line {
  position: absolute;
  bottom: 0;
  height: 1px;
  background-color: #ac2a2a;
}

.ruler-tick {
  position: absolute;
  bottom: 1px;
  height: 3px;
  width: 1px;
  background-color: #e38a8a;
}

.long-tick {
  width: 1px;
  height: 15px;
}

.tick-label {
  position: absolute;
  bottom: 2px;
  font-size: 8px;
  left: 50%;
  transform: translateX(2%);
  white-space: nowrap;
}

.cur-shadow {
  background: rgba(10, 123, 224, 0.3);
  height: 30px;
  position: absolute;
}
</style>