<template>
    <div class="flow_container">
    <div class="btn_container">
      <div class="instState">实例状态：<span :class="instStatus">{{ stateMap[instStatus]}}</span></div>
      <el-button key=" translateCenter" type="primary" @click="() => lfRef.translateCenter()">居中</el-button>
      <el-button key="fitView" type="primary" @click="() => lfRef.fitView()">适应屏幕</el-button>
       <el-button v-if="['RUNNING','PAUSED'].includes(instStatus)" type="primary" @click="stopFlow">停止</el-button>
       <el-button v-if="instStatus === 'RUNNING'" type="primary" @click="pauseFlow">暂停</el-button>
       <el-button v-if="instStatus === 'PAUSED'" type="primary" @click="restartFlow">恢复</el-button>
    </div>
    <div ref="containerRef" class="containerRef"></div>
  </div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import LogicFlow from "@logicflow/core";
import { Group } from "@logicflow/extension";
import "@logicflow/core/es/index.css";
import { convertNodeRedToLogicFlow, recursiveFilter, changeOtherNodeState } from '@/utils/convertNodeRedToLogicFlow'
import { registerCustomNode } from "./customFlowNode";
import { registerCustomGroup } from "./CustomGroup";
import { getLogicFlow } from '@/api/test/log'
import { pauseInst, resumeInst, stopInst } from '@/api/device/terminal'
import { ElMessage } from 'element-plus'

const containerRef = ref(null);
const lfRef = ref(null);
// 在新窗口的脚本中
const queryParams = new URLSearchParams(window.location.search);
const instId = queryParams.get('instId') || '';
const taskId = queryParams.get('taskId') || '';
const itemId = queryParams.get('itemId') || '03e0842c2fd7ab7575636a473aeefc89';

const data = {
  nodes: [
    {
      id: "custom-node-1",
      text: "node-1",
      type: "CustomNode",
      x: 100,
      y: 100,
    },
    {
      id: 'custom-node-2',
      type: 'CustomNode',
      x: 300,
      y: 300,
      text: 'node-2',
    },
  ],
  // 边
  edges: [
    {
      type: 'polyline',
      sourceNodeId: 'custom-node-1',
      targetNodeId: 'custom-node-2',
    },
  ],
};

const dataNodes = ref([])

const loadNodeRedData = async () => {
    const {nodes, edges} = await convertNodeRedToLogicFlow(itemId)
    lfRef.value.render({
        nodes,
        edges
    })
    dataNodes.value = nodes
    setTimeout(() => {
      lfRef.value.fitView()
    }, 20)
    getLog()
}

const getLog = async () => {
    const res = await getLogicFlow({
      instId,
      taskId,
      itemId
    })
    if (res.code === 200) {
      const arr = res.data.filter(item => {
        return item.nodeType
      })
      const map = new Map()
      arr.forEach(item => {
        if (['inject', 'start'].includes(item.nodeType)) { // , 'end'
          map.set(item.nodeId, {
            state: 'success',
            nodeType: item.nodeType,
            input: item.params
          })
        } else {
          let obj
          if (map.has(item.nodeId)) {
            obj = map.get(item.nodeId)
          } else {
            obj = {
              nodeType: item.nodeType,
            }
          }
          if (item.paramsType === 'INPUT') {
            obj.state = item.instStatus.toLowerCase(),
            obj.input = item.instStatus === 'FAILED' ? item.params : item.message
          } else {
            obj.state = item.instStatus.toLowerCase() === 'running' ? 'success' : item.instStatus.toLowerCase(),
            obj.output = item.instStatus === 'FAILED' ? item.message : item.params
          }
          map.set(item.nodeId, obj)
        }
      });

      for (const [key, value] of map) {
        lfRef.value.setProperties(key, value)
      }
      changeOtherNodeState(dataNodes.value, lfRef.value)
      if (arr[arr.length - 1].nodeType !== 'end' && arr[arr.length - 1].instStatus !== 'FAILED') {
        setTimeout(() => {
          getLog()
        }, 2000)
      }
    }
}

const stopFlow = async () => {
  const res = await stopInst(instId)
  if (res.code === 200) {
    ElMessage.success('停止成功')
    getInstDetail()
  } else {
    ElMessage.error(res.msg)
  }
}

const pauseFlow = async () => {
  const res = await pauseInst(instId)
  if (res.code === 200) {
    ElMessage.success('暂停成功')
    getInstDetail()
  } else {
    ElMessage.error(res.msg)
  }
}

const restartFlow = async () => {
  const res = await resumeInst(instId)
  if (res.code === 200) {
    ElMessage.success('恢复成功')
    getInstDetail()
  } else {
    ElMessage.error(res.msg)
  }
}

const instStatus = ref('RUNNING')
const stateMap = {
  SUCCESS: "已完成",
  RUNNING: "执行中",
  FAILED: "失败",
  PAUSED: "已暂停",
  STOPPED: "已终止"
};

const getInstDetail = async () => {
  const res = await getLogicFlow({
      instId,
      taskId,
      itemId
    })
  if (res.code === 200) {
    const item = res.data[res.data.length - 1]
    instStatus.value = item.instStatus
  }
}

onMounted(() => {
  if (containerRef.value) {
    const lf = new LogicFlow({
      container: containerRef.value,
      isSilentMode: true, 
      adjustNodePosition: true,
      stopZoomGraph: false,
      stopScrollGraph: false,
      stopMoveGraph: false,
      autoExpand: true,
      adjustEdgeStartAndEnd: true,
      allowRotate: false,
      edgeTextEdit: false,
      keyboard: {
        enabled: true,
      },
      partial: true,
      background: {
        color: "#FFFFFF",
      },
      grid: true,
      edgeTextDraggable: false,
      nodeTextEdit: false, //节点是否可编辑。false不可编辑
      textEdit: false, //是否开启文本编辑
      style: {
        inputText: {
          background: "black",
          color: "white",
        },
      },
      idGenerator(type) {
        return type + "_" + Math.random();
      },
      plugins: [Group],
      group: {
        foldable: true, // 启用折叠功能
        foldSize: 30, // 折叠后显示的图标尺寸
      },
    });

    // 注册自定义节点
    registerCustomNode(lf)
    registerCustomGroup(lf)
    // 渲染数据 data
    lf.render(data);

    lf.on('node:dragstart', (data, e) => {
      lfRef.value.setProperties(data.data.id, {
        nowTime: new Date().getTime()
      })
    })

    // 监听子节点拖动事件
    lf.on("node:mousemove", ({ data, e }) => {
      const { nodes } = lf.getGraphData();
      const arr = recursiveFilter(nodes, data.id)
      arr.forEach(item => {
        lf.getNodeModelById(item.id).updateSize()
      })
    });

    // 监听子节点拖动事件
    lf.on("blank:drop", () => {
      getLog()
    });

    lfRef.value = lf;
  }
  loadNodeRedData()
  getInstDetail()
});
</script>
<style lang="scss" scoped>
.flow_container {
  width: 100%;
  height: 100%;
  position: relative;

  .btn_container {
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: end;
    position: absolute;
    right: 10px;
    top: 0;
    z-index: 2;

    .instState {
      margin-right: 12px;
      font-size: 16px;
      font-weight: bold;

      .RUNNING, .PAUSED, .STOPPED {
        color: #8bbf86;
      }

      .SUCCESS {
        color: green;
      }

      .FAILED {
        color: rgb(128, 41, 0);
      }
    }
  }

  :deep(.containerRef) {
    width: 100%;
    height: 100%;

    .lf-graph {
      width: 100% !important;
      height: 100% !important;
    }
  }
}
</style>