<template>
  <div class="flow_region">
    <div class="nodes-wrap" align="center">
      <el-button
        style="width: 75%;margin-top: 5px;margin-bottom: 5px;"
        type="primary" @click="save">保存</el-button>
      <el-button
        style="width: 75%;margin-left: 0;margin-top: 5px;margin-bottom: 5px;"
        type="info" @click="test">测试</el-button>
      <el-button
        style="width: 75%;margin-left: 0;margin-bottom: 5px;"
        @click="returnBack">返回</el-button>

      <div>
        <el-divider content-position="left">基础</el-divider>
        <div v-for="item in nodeTypeList.filter(node => node.partition === 'basis')" :key="item.type" class="node" draggable="true" @dragstart="drag($event, item)">
          <div class="log">
            <img :src="item.logImg" alt="">
          </div>
          <div class="name">{{item.typeName}}</div>
        </div>
        <el-divider content-position="left">数据输入</el-divider>
        <div v-for="item in nodeTypeList.filter(node => node.partition === 'req')" :key="item.type" class="node" draggable="true" @dragstart="drag($event, item)">
          <div class="log">
            <img :src="item.logImg" alt="">
          </div>
          <div class="name">{{item.typeName}}</div>
        </div>
        <el-divider content-position="left">数据处理</el-divider>
        <div v-for="item in nodeTypeList.filter(node => node.partition === 'operation')" :key="item.type" class="node" draggable="true" @dragstart="drag($event, item)">
          <div class="log">
            <img :src="item.logImg" alt="">
          </div>
          <div class="name">{{item.typeName}}</div>
        </div>
        <el-divider content-position="left">数据输出</el-divider>
        <div v-for="item in nodeTypeList.filter(node => node.partition === 'resp')" :key="item.type" class="node" draggable="true" @dragstart="drag($event, item)">
          <div class="log">
            <img :src="item.logImg" alt="">
          </div>
          <div class="name">{{item.typeName}}</div>
        </div>
      </div>
    </div>
    <div id="flowWrap" ref="flowWrap" class="flow-wrap" @drop="drop($event)" @dragover="allowDrop($event)"
    style="width: 98%;height: 790px;margin-left: 10px;margin-right: 10px;">
      <div id="flow">
        <div v-show="auxiliaryLine.isShowXLine" class="auxiliary-line-x" :style="{width: auxiliaryLinePos.width, top:auxiliaryLinePos.y + 'px', left: auxiliaryLinePos.offsetX + 'px'}" />
        <div v-show="auxiliaryLine.isShowYLine" class="auxiliary-line-y" :style="{height: auxiliaryLinePos.height, left:auxiliaryLinePos.x + 'px', top: auxiliaryLinePos.offsetY + 'px'}" />
        <flowNode v-for="item in data.nodeList" :id="item.id" :key="item.id" :node="item" :data="data" @setNodeName="setNodeName" @deleteNode = "deleteNode" @changeLineState="changeLineState" />
      </div>
    </div>

  </div>
</template>

<script>
import {jsPlumb} from "jsplumb"
import {nodeTypeList} from './config/init'
import {jsplumbConnectOptions, jsplumbSetting, jsplumbSourceOptions, jsplumbTargetOptions} from './config/commonConfig'
// import data from "./config/data.json"
import flowNode from "./components/node-item"
import {batch, listNode} from "../../../api/quest/node";
import {GenNonDuplicateID} from "../../../common/until";
import panzoom from "panzoom";
import methods from "./config/methods";
import {execute, testExecute} from "../../../api/quest/task";

export default {
  name: "FlowEdit",
  components: {
    flowNode
  },
  data() {
    return {
      jsPlumb: null,
      currentItem: null,
      nodeTypeList: nodeTypeList,
      nodeTypeObj: {},
      data: {
        nodeList:[],
        lineList:[]
      },
      checkData: {
        nodeList:[],
        lineList:[]
      },
      selectedList: [],
      jsplumbSetting: jsplumbSetting,
      jsplumbConnectOptions: jsplumbConnectOptions,
      jsplumbSourceOptions: jsplumbSourceOptions,
      jsplumbTargetOptions: jsplumbTargetOptions,
      auxiliaryLine: { isShowXLine: false, isShowYLine: false},  //对齐辅助线是否显示
      auxiliaryLinePos: { width: '100%', height: '100%', offsetX: 0, offsetY: 0, x: 20, y: 20 },
      commonGrid: [5, 5], //节点移动最小距离
      selectModuleFlag: false, //多选标识
      rectAngle: {
        px: '',  //多选框绘制时的起始点横坐标
        py: '',  //多选框绘制时的起始点纵坐标
        left: 0,
        top: 0,
        height: 0,
        width: 0
      },
      taskCode: this.$route.query.taskCode,
      flag: true
    };
  },
  mounted() {
    this.getList(); //参数查询方法
    this.jsPlumb = jsPlumb.getInstance();
    this.fixNodesPosition()
    this.$nextTick(() => {
      setTimeout(() => {
        this.init()
      },1500)
    });
  },
  methods: {
    ...methods,
    // 查询数据库节点信息并整合成jsPlumb格式
    getList() {
      listNode({taskCode: this.taskCode}).then(res => {
        const rows = res.data.rows
        for (let i = 0; i < rows.length; i++) {
          const r = flowNode.methods.toJsPlumbNode(rows[i])
          // 节点添加
          this.data.nodeList.push({
            id: r.node.id,
            type: r.node.type,
            typeName: r.node.typeName,
            nodeName: r.node.nodeName,
            top: r.node.top,
            left: r.node.left
          })
          this.checkData.nodeList.push({
            id: r.node.id,
            type: r.node.type,
            typeName: r.node.typeName,
            nodeName: r.node.nodeName,
            top: r.node.top,
            left: r.node.left
          })
          // 连线添加
          if (r.line) {
            r.line.forEach(v => {
              this.data.lineList.push({
                from: v.from,
                to: v.to
              });
              this.checkData.lineList.push({
                from: v.from,
                to: v.to
              });
            })
          }
        }
        // 节点图片配置添加
        this.nodeHandle()
        // 连线去重
        this.data.lineList = this.lineHandle(this.data.lineList)
        this.checkData.lineList = this.lineHandle(this.data.lineList)
      })
    },
    // 节点批量处理-初始化
    nodeHandle() {
      // 节点图片配置添加
      this.data.nodeList.forEach(node => {
        nodeTypeList.forEach(v => {
          if (node.type === v.type) {
            node.typeName = v.typeName
            node.logImg = v.logImg
            node.log_bg_color = v.log_bg_color
          }
        })
      })
    },
    // 连线去重
    lineHandle(lineList) {
      let map = new Map();
      lineList.forEach(item => {
        const key = item.from + '->' + item.to;
        if (!map.has(key)) {
          map.set(key, item);
        }
      });
      return Array.from(map.values());
    },
    /** 参数处理 */
    handleSubmit() {
      // 1. 获取所有节点与连线信息
      const nodeList = this.data.nodeList
      const lineList = this.lineHandle(this.data.lineList)
      this.checkData.nodeList = this.data.nodeList
      this.checkData.lineList = this.data.lineList

      console.log(this.data)
      // 2. 处理所有信息,将jsPlumb类型 ==> 数据表类型
      const nodeData = []
      nodeList.forEach(node => {
        let preLine = ''
        let nextLine = ''
        lineList.forEach(line => {
          // 如果节点的id是起点
          if (node.id === line.from){
            // 给下一节点标识赋值
            nextLine = line.to
          }
          // 如果节点id是终点
          if (node.id === line.to){
            // 给上一节点标识赋值
            preLine = line.from
          }
        })
        nodeData.push(flowNode.methods.toMysqlNode(node,preLine,nextLine,this.taskCode))
      })
      return nodeData;
    },
    // 测试按钮
    test() {
      const nodeData = this.handleSubmit();
      testExecute(nodeData).then(res => {
        this.$message.success(res.data)
      })
    },
    // 保存按钮
    save() {
      const nodeData = this.handleSubmit();
      // 激活接口将参数保存到数据库
      batch(nodeData,this.$route.query.taskCode).then(res => {
        this.$message.success(res.msg)
      })
    },
    // 返回校验
    returnBack() {
      const newNodeList = this.data.nodeList
      const oldNodeList = this.checkData.nodeList
      const newLineList = this.data.lineList
      const oldLineList = this.checkData.lineList
      // this.$router.push({path: '/quest/task'})
      if (this.checkNodeList(newNodeList,oldNodeList) && this.checkLineList(newLineList,oldLineList)){
        this.$router.push({path: '/quest/task'})
      }else{
        this.checkReturn()
      }
    },
    // 节点校验
    checkNodeList(newNodeList, oldNodeList) {
      let newLen = newNodeList.length
      let oldLen = oldNodeList.length
      if (newLen !== oldLen) return false;
      for (let i = 0; i < newLen; i++) {
        if (newNodeList[i].id === oldNodeList[i].id &&
          newNodeList[i].nodeName === oldNodeList[i].nodeName &&
          newNodeList[i].type === oldNodeList[i].type &&
          newNodeList[i].left === oldNodeList[i].left &&
          newNodeList[i].top === oldNodeList[i].top){
          continue;
        }
        return false;
      }
      return true;
    },
    checkLineList(newLineList,oldLineList) {
      let newLen = newLineList.length
      let oldLen = oldLineList.length
      if (newLen !== oldLen) return false;
      for (let i = 0; i < newLen; i++) {
        if (newLineList[i].from === oldLineList[i].from &&
          newLineList[i].to === oldLineList[i].to){
          continue;
        }
        return false;
      }
      return true;
    },
    // 未保存 返回按钮
    checkReturn() {
      this.$confirm('更改未保存,是否保存?', '未保存提示', {
        confirmButtonText: '保存',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.save()
        this.$router.push({path: '/quest/task'})
      }).catch(() => {
        this.$message({
          type: 'success',
          message: '返回成功'
        });
        this.$router.push({path: '/quest/task'})
      });
    },
    // 修改状态更新
    checkFlag(){
      this.flag = false
    }
  }
};
</script>

<style lang="less" scoped>
.flow_region {
  display: flex;
  width: 98%;
  height: 90%;
  margin: 20px auto;
  border: 1px solid #ccc;
  .nodes-wrap {
    width: 150px;
    height: 790px;
    border-right: 1px solid #ccc;
    .node {
      display: flex;
      height: 40px;
      width: 80%;
      margin: 5px auto;
      border: 1px solid #ccc;
      line-height: 40px;
      &:hover{
        cursor: grab;
      }
      &:active{
        cursor: grabbing;
      }
      .log {
        width: 40px;
        height: 40px;
      }
      .name {
        width: 0;
        flex-grow: 1;
      }
    }
  }
  .flow-wrap {
    height: 100%;
    position: relative;
    overflow: hidden;
    outline: none !important;
    flex-grow: 1;
    background-image: url("../../../assets/point.png");
    #flow {
      position: relative;
      width: 100%;
      height: 100%;
      .auxiliary-line-x {
        position: absolute;
        border: .5px dashed #2ab1e8;
        z-index: 998;
      }
      .auxiliary-line-y {
        position: absolute;
        border: .5px dashed #2ab1e8;
        z-index: 998;
      }
    }
  }
}
</style>

<style lang="less">
.jtk-connector.active{
  z-index: 998;
  path {
    stroke: #150042;
    stroke-width: 1.5;
    animation: ring;
    animation-duration: 3s;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    stroke-dasharray: 5;
  }
}
@keyframes ring {
  from {
    stroke-dashoffset: 50;
  }
  to {
    stroke-dashoffset: 0;
  }
}
</style>
