<template>
  <div class="workflow-graph-panel">
    <div class="workflow-graph-panel-tool">
      <div class="workflow-graph-panel-tool-btn" @click="reduceGraph">
        <minus-outlined />
      </div>

      <div class="workflow-graph-panel-tool-zoom">
        <span>{{ zoomPercentage }}%</span>
      </div>

      <div class="workflow-graph-panel-tool-btn" @click="amplifyGraph">
        <plus-outlined />
      </div>

      <div class="workflow-graph-panel-tool-btn" @click="redoGraph">
        <redo-outlined />
      </div>
    </div>
    <!-- 画布 -->
    <div ref="container" style="width: 100%; height: 100%"></div>
  </div>
</template>

<script>
import { defineComponent, getCurrentInstance, onMounted, onUnmounted, ref } from 'vue';
import { FlowDesignApi } from '../../../design/api/FlowDesignApi';
import registerCustomVueShape from '../../../../../flow-design/shape/custom-vue-shape';
import { WorkflowGraph } from '../../../../../flow-design/model/workflow-graph';
import { useEventListener } from '@vueuse/core';

// 注册自定义x6元素
registerCustomVueShape();

export default defineComponent({
  name: 'FlowView',
  props: {
    definitionId: {
      type: String,
      default: ''
    }
  },
  setup(props) {
    const { proxy } = getCurrentInstance();

    // 画布dom
    const container = ref(null);
    // 画布
    let workflowGraph;

    // 模型数据
    const modelDetail = ref();
    // 加载状态
    const modelLoading = ref(false);

    const definitionId = ref('');

    // 图标缩放百分比
    const zoomPercentage = ref(100);

    /**
     * 获取流程图Json
     */
    const getGraphJson = async () => {
      modelLoading.value = true;
      await FlowDesignApi.flowDesignDetail({ definitionId: definitionId.value })
        .then(res => {
          let modelData = res.data;
          let xsixGraphJson = modelData?.xsixGraphJson?.nodeGraph;
          if (xsixGraphJson) {
            if (xsixGraphJson?.cells?.length > 0) {
              xsixGraphJson.cells = xsixGraphJson.cells.filter(item => !(item.shape === 'rect' && !item.data));
            }
            modelDetail.value = xsixGraphJson;
          }
        })
        .finally(() => {
          modelLoading.value = false;
        });
    };

    /**
     * 放大图表
     */
    const amplifyGraph = () => {
      if (workflowGraph.graph) {
        if (zoomPercentage.value < 200) {
          zoomPercentage.value = zoomPercentage.value + 10;
          workflowGraph.graph.zoom(0.1);
        }
      }
    };

    /**
     * 缩小图表
     */
    const reduceGraph = () => {
      if (workflowGraph.graph) {
        if (zoomPercentage.value > 10) {
          zoomPercentage.value = zoomPercentage.value - 10;
          workflowGraph.graph.zoom(-0.1);
        }
      }
    };

    /**
     * 还原图表
     */
    const redoGraph = () => {
      if (workflowGraph.graph) {
        zoomPercentage.value = 100;
        workflowGraph.graph.zoomTo(1);
        // 将画布中元素缩小或者放大一定级别，让画布正好容纳所有元素，可以通过 maxScale 配置最大缩放级别
        workflowGraph.graph.zoomToFit({ maxScale: 1 });
        // 将画布中元素居中展示
        workflowGraph.graph.centerContent();
      }
    };

    onMounted(async () => {
      definitionId.value = props.definitionId;

      await getGraphJson();

      // 初始化画布
      workflowGraph = new WorkflowGraph(proxy, container.value, () => {}, true);

      // 加载json
      let cells = modelDetail.value?.cells;
      if (cells) {
        // 设置线和节点的颜色
        cells.forEach(cell => {
          // 去除线的箭头
          if (cell.shape === 'edge') {
            cell.attrs.line.targetMarker.name = 'path';
          } else if (cell.shape === 'custom-vue-shape') {
            let cellGetData = JSON.parse(cell.data);
            cellGetData.data.borderColor = '#a6a6a6';
            cell.data = JSON.stringify(cellGetData);
          }
        });
        workflowGraph.graph.fromJSON(cells);
        // 将画布中元素缩小或者放大一定级别，让画布正好容纳所有元素，可以通过 maxScale 配置最大缩放级别
        workflowGraph.graph.zoomToFit({ maxScale: 1 });
        // 将画布中元素居中展示
        workflowGraph.graph.centerContent();
      }

      // 监听快捷键
      useEventListener(document, 'wheel', e => {
        // 检查是否同时按下了 alt 键
        if (e.altKey) {
          // 判断滚轮方向
          if (e.deltaY > 0) {
            // 向下滚动 缩小画布
            reduceGraph();
          } else if (e.deltaY < 0) {
            // 向上滚动 放大画布
            amplifyGraph();
          }
        }
      });
    });

    onUnmounted(() => {
      // 销毁画布
      workflowGraph?.destroy?.();
      // 清除事件
      workflowGraph?.clearEventListenter?.();
    });

    return {
      modelDetail,
      container,
      zoomPercentage,
      amplifyGraph,
      redoGraph,
      reduceGraph
    };
  }
});
</script>

<style scoped lang="less">
.workflow-graph-panel {
  width: 100%;
  height: 100%;
}

.workflow-graph-panel-tool {
  background-color: rgb(255, 255, 255, 0.5);
  position: absolute;
  z-index: 1;
  right: 16px;
  width: auto;
  height: auto;
  margin-top: 12px;
  display: flex;
}

.workflow-graph-panel-tool-btn, .workflow-graph-panel-tool-zoom {
  cursor: pointer;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.workflow-graph-panel-tool-btn:hover {
  background-color: #eee;
}
</style>
