<script setup lang="ts" name="FlowDesignPreview">
import { ref, type Ref, computed, provide, inject, nextTick, watch, onMounted, onBeforeUnmount, getCurrentInstance, type ComponentInternalInstance } from 'vue'
import PreviewNodesGroup from './Nodes/index.vue' // 节点&连线
import PreviewFvPolyline from './Polyline/index.vue'
import PreviewArrow from './Marker/PreviewArrow.vue'
import PreviewPuzzleNormalShadow from './Marker/PreviewPuzzleNormalShadow.vue'
import { init as initSvgWrap, zoomSize, resetPosition, destroy } from './Hooks/SvgWrap'
import * as variables from './Hooks/variables'

import type { INodes, IPaths, IState } from './utils/INodes'

const props = defineProps<{
  nodeData: any
}>()

const {
  x,
  y,
  oldX,
  oldY,
  scale,
  oldScale,
  pageX,
  pageY,
  state
} = variables

const nodeRunList = ref([])
const nodeConfig = ref([])
const svgWrapRef = ref<SVGSVGElement | null>(null)

provide('svgWrapRef', svgWrapRef)
provide('scale', scale)
provide('oldScale', oldScale)
provide('x', x)
provide('y', y)
provide('oldX', oldX)
provide('oldY', oldY)
provide('pageX', pageX)
provide('pageY', pageY)
provide('nodeRunList', nodeRunList)
provide('nodeConfig', nodeConfig)

// 矩阵变换属性
const matrix = computed(() => `matrix(${scale.value},0,0,${scale.value},${x.value},${y.value})`)

watch(() => props.nodeData, () => {
  flowEnginePreview()
}, { deep: true })
onBeforeUnmount(() => {
  destroy()
})

// 初始流程预览数据
function flowEnginePreview() {
  nodeRunList.value = props.nodeData.nodeRunList || []
  nodeConfig.value = JSON.parse(JSON.stringify(props.nodeData.nodeList)).map(item => {
    item.nodePath = JSON.parse(item.nodePath)
    item.userTypeParams = item.userTypeParams ? JSON.parse(item.userTypeParams) : []
    item.inputNodeCode = item.inputNodeCode.split(',').filter(Boolean)
    item.outputNodeCode = item.outputNodeCode.split(',').filter(Boolean)
    item.nodeButtonConfig = item.nodeButtonConfig || []
    item.nodeMonitorConfig = item.nodeMonitorConfig || []
    item.nodeSubprocessesConfig = item.nodeSubprocessesConfig || []
    return item
  })
  nextTick(() => {
    // 使画布所有元素自适应画布大小，居中
    initSvgWrap(svgWrapRef)
    resetPosition(nodeConfig.value)
  })
}
</script>

<template>
  <div class="fv-container">
    <div class="zoom">
      <van-divider vertical style="margin:0" />
      <el-tooltip effect="dark" content="缩小" placement="bottom">
        <div :class="'zoom-out' + (scale <= 0.1 ? ' disabled' : '')" @click="zoomSize(1)" />
      </el-tooltip>
      <van-divider vertical style="margin:0" />
      <el-tooltip effect="dark" content="放大" placement="bottom">
        <div :class="'zoom-in'" @click="zoomSize(2)" />
      </el-tooltip>
      <van-divider vertical style="margin:0" />
      <el-tooltip effect="dark" content="原尺寸" placement="bottom">
        <div class="zoom-original" @click="zoomSize(3)" />
      </el-tooltip>
      <van-divider vertical style="margin:0" />
      <el-tooltip effect="dark" content="适应尺寸" placement="bottom">
        <div class="zoom-adapt" @click="resetPosition(nodeConfig)" />
      </el-tooltip>
    </div>
    <svg
      ref="svgWrapRef"
      xmlns="http://www.w3.org/2000/svg"
      version="1.1"
      width="100%"
      height="100%"
      class="fv-wrap">
      <g class="viewport" :transform="matrix">
        <!-- 连线层 -->
        <PreviewFvPolyline />
        <!-- 节点层 -->
        <PreviewNodesGroup />
      </g>
      <!-- 定义形状 -->
      <defs>
        <!-- 连线箭头 -->
        <PreviewArrow />
        <!-- 阴影高亮 -->
        <PreviewPuzzleNormalShadow />
      </defs>
    </svg>
  </div>
</template>

<style lang="less" scoped>
.fv-container {
  width: 100%;
  height: 100%;
}
/* 缩放 */
.zoom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: fixed;
  z-index: 10;
  height: 40px;
  // width: 125px;
  right: 16px;
  margin-top: 16px;
  user-select: none;
  background-color: #fff;
  border: 1px solid #999;
  border-radius: 3px;
  .zoom-undo,
  .zoom-redo,
  .zoom-in,
  .zoom-out,
  .zoom-original,
  .zoom-adapt,
  .zoom-reset,
  .zoom-restore {
    margin: 0 4px;
    width: 30px;
    height: 30px;
    color: #c1c1cd;
    cursor: pointer;
    background-size: 100%;
    background-repeat: no-repeat;
    &.disabled {
      opacity: .5;
    }
  }
  .zoom-undo {
    background: #fff url(./svg/undo.svg) center / 80% no-repeat;
  }
  .zoom-redo {
    background: #fff url(./svg/redo.svg) center / 80% no-repeat;
  }
  .zoom-in {
    background: #fff url(./svg/zoom-in.svg) center / 80% no-repeat;
  }
  .zoom-out {
    background: #fff url(./svg/zoom-out.svg) center / 80% no-repeat;
  }
  .zoom-reset {
    background: #fff url(./svg/zoom-reset.svg) center / 80% no-repeat;
  }
  .zoom-original {
    background: #fff url(./svg/zoom-original.svg) center / 80% no-repeat;
  }
  .zoom-adapt {
    background: #fff url(./svg/zoom-adapt.svg) center / 80% no-repeat;
  }
  .zoom-restore {
    background: #fff url(./svg/zoom-restore.svg) center / 80% no-repeat;
  }
}

.fv-wrap {
  display: block;
  user-select: none;
  // pointer-events: none;
}

</style>