<template>
  <div class="graph-main">
    <div class="legend-box"  v-show="!legendHide">
      <div class="item-row" v-for="(value, key) in legendList" :key="key">
        <div class="point" :style="'background-color:' + value.color"></div>
        <div class="label">{{ value.label }}</div>
      </div>
    </div>
    <div :id="id" style="width: 100%; height: 100%"></div>
  </div>
</template>

<script>
import request from '@/utils/request';
import G6 from '@antv/g6';

var graphObj = {};

export default {
  data() {
    return {
      ontologyId: '',
      id: Math.round(Math.random() * 10000000).toString(),
      graph: null,
      graphData: null,
      legendHide: false,
      legendList: {
        "armyType": {label: '军种', color: 'rgb(76,142,218)'},
        "control": {label: '控制系统', color: 'rgb(236,181,201)'},
        "engine": {label: '发动机', color: 'rgb(241,102,103)'},
        "fault": {label: '故障信息', color: 'rgb(141,204,147)'},
        "faultCase": {label: '故障案例', color: 'rgb(156,33,234)'},
        "oriPlane": {label: '原飞机', color: 'rgb(255,196,84)'},
        "part": {label: '部件', color: 'rgb(86,148,128)'},
        "place": {label: '发生地', color: 'rgb(217,200,174)'},
        "plane": {label: '飞机', color: 'rgb(87,199,227)'}
      }
    }
  },
  created() {
    this.ontologyId = this.$route.query.id;
  },
  mounted() {
  },
  methods: {
    initGraph: function (cmd, flag, clickNodeFun, legendHide) { // 是否隐藏图例
      if(legendHide) {
        this.legendHide = true;
      }
      let graph = graphObj[this.id];
      this.$nextTick(() => {
        this.destroyGraph();
        let _width = document.getElementById(this.id).clientWidth;
        let _height = document.getElementById(this.id).clientHeight;
        // 创建 G6 图实例
        if (graph == undefined || graph == null) {
          graph = new G6.Graph({
            container: this.id, // 指定图画布的容器 id，与第 9 行的容器对应
            // 画布宽高
            width: _width,
            height: _height,
            layout: {
              type: 'force',
              nodeStrength: -0,
              nodeSize: 80,
              preventOverlap: true,
              edgeStrength: 0.1
            },
            modes: {
              // Defualt mode
              default: ['drag-node',
                {
                  type: 'drag-canvas',
                  enableOptimize: true, // enable the optimize to hide the shapes beside nodes' keyShape
                },
                {
                  type: 'zoom-canvas',
                  enableOptimize: true, // enable the optimize to hide the shapes beside nodes' keyShape
                },
                {
                  type: 'tooltip',
                  formatText: function formatText(model) {
                    let name = '';
                    let argumentsStr = '';
                    if (model.label) name = model.label + '<br/>';
                    if (model.arguments && model.arguments.length > 0) {
                      model.arguments.forEach(arg => {
                        argumentsStr += arg.role + "：" + arg.argument + '<br/>';
                      });
                    }
                    const text = `${name} ${argumentsStr}`;
                    return text;
                  },

                  shouldUpdate: function shouldUpdate() {
                    return true;
                  },
                },
              ],
            },
            defaultNode: {
              size: 20,
              color: '#4b4b4b',
              label: 'name',
              style: {
                lineWidth: 2,
                fill: '#68BDF6'
              },
              labelCfg: {
                position: 'bottom',
                style: {
                  fontSize: 14,
                  fill: '#454545'
                }
              }
            },
            defaultEdge: {
              style: {
                stroke: '#b3b3b3',
                lineAppendWidth: 10, // Enlarge the range the edge to be hitted
              },
              labelCfg: {
                autoRotate: false,
                style: {
                  fontSize: 14,
                  fill: '#848484'
                }
              },
            },
            nodeStateStyles: {
              yourStateName: {
                stroke: '#f00',
                lineWidth: 3,
              },
            },
            edgeStateStyles: {
              yourStateName: {
                stroke: '#f00',
                lineWidth: 3,
              },
            },
          });

          /*拖动节点-start*/
          const forceLayout = graph.get('layoutController').layoutMethod;
          graph.on('node:dragstart', function (e) {
            graph.layout();
            refreshDragedNodePosition(e);
          });
          graph.on('node:drag', function (e) {
            if (forceLayout) {
              forceLayout.execute();
            }
            refreshDragedNodePosition(e);
          });
          graph.on('node:dragend', function (e) {
            e.item.get('model').fx = null;
            e.item.get('model').fy = null;
          });
          /*拖动节点-end*/

          graph.on('node:click', (e) => {
            let node = e.item._cfg.model;
            if (clickNodeFun) {
              clickNodeFun(node);
            }
            this.clearStates();
            graph.setItemState(e.item, 'yourStateName', true);
          });

          graph.on('canvas:click', (e) => {
            this.clearStates();
          });

          graphObj[this.id] = graph;

        }
        if (flag) {
          this.importData(cmd);
        } else {
          this.queryData(cmd);
        }
      });
    },
    importData({nodes, edges}) { // 查询图空间内节点关系
      let graph = graphObj[this.id];
      // 更新颜色数据
      nodes.forEach(node => {
        node.style = {
          lineWidth: 2,
          fill: this.legendList[node._label].color || "#68BDF6"
        };
      });

      this.graphData = {
        nodes: nodes,
        edges: edges
      };
      // 读取数据
      graph.data(this.graphData);
      // 渲染图
      graph.render();
    },
    queryData({path, qo}) { // 查询图空间内节点关系
      let graph = graphObj[this.id];
      request({
        url: path,
        method: 'post',
        data: qo
      }).then(res => {
        res.data.nodes.forEach(node => {
          node.label = node.properties.name;
          node.id = node.id.toString();
        });
        res.data.relations.forEach(edge => {
          delete edge.id;
          edge.source = edge.source.toString();
          edge.target = edge.target.toString();
          if (edge.source === edge.target) {
            edge.type = 'loop';
          } else {
            delete edge.type;
          }
        });
        this.importData({
          nodes: res.data.nodes,
          edges: res.data.relations
        });
        // this.graphData = {
        //   nodes: res.data.nodes,
        //   edges: res.data.relations
        // };
        // // 读取数据
        // graph.data(this.graphData);
        // // 渲染图
        // graph.render();
      });
    },
    clearStates() { // 清空选中状态
      let graph = graphObj[this.id];
      graph.getNodes().forEach((node) => {
        graph.clearItemStates(node);
      });
      graph.getEdges().forEach((edge) => {
        graph.clearItemStates(edge);
      });
    },
    destroyGraph() {
      let graph = graphObj[this.id];
      try {
        if (graph != undefined && graph != null) {
          graph.clear();
          graph = null;
          document.getElementById("mountNode").innerHTML = "";
        }
      } catch (err) {
        console.log(err);
      }
    },
  }
}

function refreshDragedNodePosition(e) {
  const model = e.item.get('model');
  model.fx = e.x;
  model.fy = e.y;
}
</script>

<style>
.g6-tooltip {
  border: 1px solid #e2e2e2;
  border-radius: 4px;
  font-size: 12px;
  color: #545454;
  background-color: rgba(255, 255, 255, 0.9);
  padding: 10px 8px;
  box-shadow: rgb(174 174 174) 0px 0px 10px;
}

.graph-main {
  position: relative;
  width: 100%;
  height: 100%;
}

.legend-box {
  position: absolute;

  top: 10px;
  left: 10px;
}

.item-row {
  float: left;
  margin-right: 15px;
}

.item-row .point {
  width: 20px;
  height: 20px;
  border-radius: 40px;
  border: 2px solid #4b4b4b;
  display: inline-block;
}

.item-row .label {
  line-height: 20px;
  height: 20px;
  float: right;
  margin-left: 5px;
}

</style>
