<template>
  <o-layout ref="centerCanvas" v-resize="editorWindowResizeHandler">
    <!-- 中间画布 -->
    <o-layout-content class="content">
      <o-scrollbar x-scrollable class="x-scrollable" :style="scrollbarStyle">
        <Editor />
      </o-scrollbar>
    </o-layout-content>
    <o-layout-footer position="absolute" class="footer">
      <o-space justify="end" align="center" style="height: 100%; margin-right: 5px">
        <o-el
          tag="span"
          :style="{ color: primaryColor, transition: `all 0.3s ${cubicBezierEaseInOut}` }"
        >
          画布缩放:
        </o-el>
        <o-slider
          :value="sliderValue"
          :min="10"
          :max="200"
          style="width: 120px"
          @update:value="handleScale"
        />
        <o-select
          :value="selectValue"
          :options="options"
          size="tiny"
          style="width: 90px"
          @update:value="handleScale"
        />
      </o-space>
    </o-layout-footer>
  </o-layout>
</template>

<script lang="ts" setup>
import { debounce } from 'lodash-es'
import { useThemeVars } from 'naive-ui'
import { useCanvasState } from 'open-data-v/designer'
import type { SelectOption } from 'open-data-v/ui'
import {
  OEl,
  OLayout,
  OLayoutContent,
  OLayoutFooter,
  OScrollbar,
  OSelect,
  OSlider,
  OSpace
} from 'open-data-v/ui'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'

import Editor from '../../Editor'

const windowWidth = ref<number>(0)
const windowHeight = ref<number>(0)
const toolBarHeight = ref<number>(35)

const sliderValue = ref<number>(100)
const selectValue = ref<string>('100%')
const scaleValue = ref<number>(1)
const canvasState = useCanvasState()
const options: SelectOption[] = [
  {
    value: 200,
    label: '200%'
  },
  {
    value: 150,
    label: '150%'
  },
  {
    value: 100,
    label: '100%'
  },
  {
    value: 80,
    label: '80%'
  },
  {
    value: 50,
    label: '50%'
  }
]

const themeVars = useThemeVars()
const { primaryColor, cubicBezierEaseInOut } = themeVars.value

const scrollbarStyle = computed(() => {
  return {
    width: windowWidth.value + 'px',
    height: windowHeight.value + 'px'
  }
})

const editorWindowResizeHandler = (entry: ResizeObserverEntry) => {
  const { width, height } = entry.contentRect
  windowWidth.value = width
  windowHeight.value = height - toolBarHeight.value
}

const handleScale = (value: number) => {
  selectValue.value = `${value}%`
  sliderValue.value = value
  changeScale(sliderValue.value)
}

const changeScale = debounce((value: number) => {
  canvasState.setScale(value)
  scaleValue.value = value / 100
}, 300)

// region 按住 alt 或 command + 滚轮缩放
const centerCanvas = ref()
function setScaleByWheel(e: WheelEvent) {
  const max = 200
  const min = 10
  const limit = 10

  const { altKey, metaKey, deltaY } = e
  let scale = sliderValue.value
  if (altKey || metaKey) {
    e.preventDefault()
    if (min < scale && scale < max) {
      scale = deltaY > 0 ? scale + limit : scale - limit
    } else if (scale <= min && deltaY > 0) {
      scale += limit
    } else if (scale >= max && deltaY < 0) {
      scale -= limit
    }
    handleScale(scale)
  }
}

onMounted(() => {
  centerCanvas.value.$el!.addEventListener('wheel', setScaleByWheel, false)
})

onBeforeUnmount(() => {
  centerCanvas.value.$el!.removeEventListener('wheel', setScaleByWheel, false)
})
// endregion
</script>

<style lang="less" scoped>
.content {
  box-shadow: inset 0 0 3px black;
  :deep(.n-scrollbar-content) {
    transform-origin: left top;
    transform: scale(v-bind(scaleValue));
    transition: all 0.3s;
  }
}

.footer {
  height: v-bind('toolBarHeight + "px"');
}
</style>
