import { Addon, FunctionExt, Graph, Shape } from '@antv/x6'
import { getImg } from '../index.js'
import graphData from './data/data'
import { customPorts } from './ports'
import './shape'
const insertCss = require('insert-css')

insertCss(`
  @keyframes ant-line {
    to {
        stroke-dashoffset: -1000
    }
  }
`)

export default class FlowGraph {
  static graph = null
  static stencil = null

  /**
   * 初始化方法
   * @param {*} dom 画板容器
   * @param {*} width 容器宽度
   * @param {*} height 容器高度
   * @param {*} flag 默认为true,传入false只实例化画板
   * @returns
   */
  static init(dom, width = 1200, height = 900, flag = true) {
    // 初始化 流程图画板
    this.graph = new Graph({
      background: {
        color: '#f4f4f4' // 设置画布背景颜色
      },
      container: dom,
      width: width,
      height: height,
      autoResize: true,
      grid: {
        size: 10,
        visible: true,
        type: 'doubleMesh',
        args: [
          {
            color: '#cccccc',
            thickness: 1
          },
          {
            color: '#5F95FF',
            thickness: 1,
            factor: 4
          }
        ]
      },
      scroller: {
        enabled: false,
        pageVisible: false,
        pageBreak: false,
        pannable: false
      },
      // 开启画布缩放
      mousewheel: {
        enabled: true,
        // modifiers: ['ctrl', 'meta'],
        minScale: 0.1,
        maxScale: 10,
        // 当鼠标滚轮滚动时触发缩放
        zoomOnMouseWheel: true 
      },
      interacting: {
        nodeMovable: false, // 节点是否可以被移动。
        edgeMovable: false, // 边是否可以被移动。
        edgeLabelMovable: false, // 边的标签是否可以被移动。
        arrowheadMovable: false, // 边的起始/终止箭头是否可以被移动
        vertexMovable: false, // 边的路径点是否可以被移动。
        vertexAddable: false, // 是否可以添加边的路径点。
        vertexDeletable: false // 边的路径点是否可以被删除。
      },
      connecting: {
        anchor: 'center',
        connectionPoint: 'anchor',
        allowBlank: true,
        highlight: true,
        snap: true, // 是否自动吸附
        allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
        allowNode: false, // 是否允许边链接到节点(非节点上的链接桩)
        allowBlank: false, // 是否允许连接到空白点
        allowLoop: false, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点,
        allowEdge: false, // 是否允许边链接到另一个边
        highlight: false, // 拖动边时,是否高亮显示所有可用的连接桩或节点
        connectionPoint: 'anchor', // 指定连接点
        anchor: 'center', // 指定被连接的节点的锚点
        createEdge() {
          // X6 的 Shape 命名空间中内置 Edge、DoubleEdge、ShadowEdge 三种边
          return new Shape.DoubleEdge({
            attrs: {
              // line: {
              //   // stroke: '#5F95FF',
              //   // strokeWidth: 4,
              //   // targetMarker: {
              //   //   name: 'classic',
              //   //   size: 8,
              //   // },
              //   stroke: '#1890ff',
              //   strokeDasharray: 5,
              //   targetMarker: null,//block classic diamond cross async path circle circlePlus ellipse
              //   style: {
              //     animation: 'ant-line 30s infinite linear',
              //   },
              // },
              line: {
                strokeWidth: 4,
                stroke: '#cfe7f2',
                strokeDasharray: 0,
                style: {
                  animation: 'ant-line 0s infinite linear'
                },
                targetMarker: null // 去掉箭头
              },
              outline: {
                stroke: '#456d89',
                strokeWidth: 7
              }
            },
            router: {
              name: 'metro',
              args: {
                offset: 32,
                direction: 'H'
              }
            }
          })
        },
        validateConnection({
          sourceView,
          targetView,
          sourceMagnet,
          targetMagnet
        }) {
          if (sourceView === targetView) {
            return false
          }
          if (!sourceMagnet) {
            return false
          }
          if (!targetMagnet) {
            return false
          }
          return true
        }
      },
      highlighting: {
        magnetAvailable: {
          name: 'stroke',
          args: {
            padding: 4,
            attrs: {
              strokeWidth: 4,
              stroke: 'rgba(223,234,255)'
            }
          }
        }
      },
      // 开启拖拽平移(防止冲突,按下修饰键并点击鼠标才能触发画布拖拽)
      panning: {
        enabled: true,
        // modifiers: 'shift'
      },
      resizing: true,
      rotating: true,
      selecting: {
        enabled: true,
        multiple: true,
        rubberband: true,
        movable: true,
        showNodeSelectionBox: true
      },
      snapline: true,
      history: true,
      clipboard: {
        enabled: true
      },
      keyboard: {
        enabled: true
      },
      embedding: {
        enabled: true,
        findParent({ node }) {
          const bbox = node.getBBox()
          return this.getNodes().filter((node) => {
            // 只有 data.parent 为 true 的节点才是父节点
            const data = node.getData()
            if (data && data.parent) {
              const targetBBox = node.getBBox()
              return bbox.isIntersectWithRect(targetBBox)
            }
            return false
          })
        }
      }
    })
    if (!flag) {
      // this.graph.centerContent()
      this.graph.hideGrid() // 返显渲染的时候 隐藏网格
      return this.graph
    }
    // this.initStencil()
    // this.initShape()
    // this.initGraphShape()
    // this.initEvent()
    // return this.graph
  }
  // 初始化根节点
  static initStencil() {
    this.stencil = new Addon.Stencil({
      target: this.graph,
      stencilGraphWidth: 280,
      search: { rect: true },
      collapsable: true,
      groups: [
        {
          name: 'basic',
          title: '基础节点',
          graphHeight: 180
        },
        {
          name: 'custom-image',
          title: '系统设计图',
          graphHeight: 600
        }
        // {
        //   name: 'combination',
        //   title: '组合节点',
        //   layoutOptions: {
        //     columns: 1,
        //     marginX: 60,
        //   },
        //   graphHeight: 260,
        // },
        // {
        //   name: 'group',
        //   title: '节点组',
        //   graphHeight: 100,
        //   layoutOptions: {
        //     columns: 1,
        //     marginX: 60,
        //   },
        // },
      ]
    })
    const stencilContainer = document.querySelector('#stencil')
    stencilContainer?.appendChild(this.stencil.container)
  }
  // 初始化具体每个根节点下不同类型节点
  static initShape() {
    const { graph } = this
    // 基础节点
    const r1 = graph.createNode({
      shape: 'flow-chart-rect',
      attrs: {
        body: {
          rx: 24,
          ry: 24
        },
        text: {
          text: '起始节点'
        }
      }
    })
    const r2 = graph.createNode({
      shape: 'flow-chart-rect',
      attrs: {
        text: {
          text: '流程节点'
        }
      }
    })
    const r3 = graph.createNode({
      shape: 'flow-chart-rect',
      width: 52,
      height: 52,
      angle: 45,
      attrs: {
        'edit-text': {
          style: {
            transform: 'rotate(-45deg)'
          }
        },
        text: {
          text: '判断节点',
          transform: 'rotate(-45deg)'
        }
      },
      ports: {
        groups: {
          top: {
            position: {
              name: 'top',
              args: {
                dx: -26
              }
            }
          },
          right: {
            position: {
              name: 'right',
              args: {
                dy: -26
              }
            }
          },
          bottom: {
            position: {
              name: 'bottom',
              args: {
                dx: 26
              }
            }
          },
          left: {
            position: {
              name: 'left',
              args: {
                dy: 26
              }
            }
          }
        }
      }
    })
    const r4 = graph.createNode({
      shape: 'flow-chart-rect',
      width: 70,
      height: 70,
      attrs: {
        body: {
          rx: 35,
          ry: 35
        },
        text: {
          text: '链接节点'
        }
      }
    })
    // 组合节点
    const c1 = graph.createNode({
      shape: 'flow-chart-image-rect'
    })
    const c2 = graph.createNode({
      shape: 'flow-chart-title-rect'
    })
    const c3 = graph.createNode({
      shape: 'flow-chart-animate-text'
    })
    // 节点组
    const g1 = graph.createNode({
      shape: 'groupNode',
      attrs: {
        text: {
          text: 'Group Name'
        }
      },
      data: {
        parent: true
      }
    })
    // 系统设计图
    const imgs = [
      {
        image: getImg('ldb.png')
      },
      {
        image: getImg('wft1.png')
      },
      {
        image: getImg('wft2.png')
      },
      {
        image: getImg('wft3.png')
      },
      {
        image: getImg('wft4.png')
      },
      {
        image: getImg('wft5.png')
      },
      {
        image: getImg('lqt.png')
      },
      {
        image: getImg('lqb-o.png')
      },
      {
        image: getImg('ldb-o.png')
      },
      {
        image: getImg('bh.png')
      },
      {
        image: getImg('f1.png')
      },
      {
        image: getImg('f2.png')
      },
      {
        image: getImg('f3.png')
      }
    ]
    const imgNodes = imgs.map(item => {
      return graph.createNode({
        // shape: 'flow-chart-image-rect-custom',
        // attrs: {
        //   image: {
        //     'xlink:href': item.image,
        //   }
        // }
        shape: 'image', // 可选值:Rect Circle Ellipse Polygon Polyline Path Image HTML TextBlock BorderedImage EmbeddedImage InscribedImage Cylinder
        imageUrl: item.image,
        attrs: {
          image: {
            // fill: 'yellow',
          }
        },
        width: 52,
        height: 52,
        ports: { ...customPorts }
      })
    })
    this.stencil.load([r1, r2, r3, r4], 'basic')
    this.stencil.load(imgNodes, 'custom-image')
    // this.stencil.load([c1, c2, c3], 'combination')
    // this.stencil.load([g1], 'group')
  }

  // 根据json渲染节点和边
  static initGraphShape(gd = graphData) {
    console.log(gd)
    var data = null
    data = gd
    // setInterval(() => {
    console.log(data.cells[0].position.x)
    data.cells[0].position.x += 1
    this.graph.fromJSON(data)
    const nodes = this.graph.getNodes()
    console.log(nodes)

    // }, 100);
  }

  // 连接桩显示时机
  static showPorts(ports, show) {
    for (let i = 0, len = ports.length; i < len; i = i + 1) {
      ports[i].style.visibility = show ? 'visible' : 'hidden'
    }
  }

  // 事件相关
  static initEvent() {
    const { graph } = this
    const container = document.getElementById('container')
    // 右键编辑文本
    graph.on('node:contextmenu', ({ cell, view }) => {
      console.log(view.container)
      const oldText = cell.attr('text/text')
      cell.attr('text/style/display', 'none')
      const elem = view.container.querySelector('.x6-edit-text')
      if (elem) {
        elem.innerText = oldText
        elem.focus()
      }
      const onBlur = () => {
        cell.attr('text/text', elem.innerText)
        cell.attr('text/style/display', 'inline-block')
      }
      if (elem) {
        elem.addEventListener('blur', () => {
          onBlur()
          elem.removeEventListener('blur', onBlur)
        })
      }
    })
    // 鼠标移入 显示连接桩
    graph.on('node:mouseenter', FunctionExt.debounce(() => {
      const ports = container.querySelectorAll('.x6-port-body')
      this.showPorts(ports, true)
    }), 500)
    // 鼠标移出 隐藏连接桩
    graph.on('node:mouseleave', () => {
      const ports = container.querySelectorAll('.x6-port-body')
      this.showPorts(ports, false)
    })

    graph.on('node:collapse', ({ node, e }) => {
      e.stopPropagation()
      node.toggleCollapse()
      const collapsed = node.isCollapsed()
      const cells = node.getDescendants()
      cells.forEach(n => {
        if (collapsed) {
          n.hide()
        } else {
          n.show()
        }
      })
    })
    // backspace
    graph.bindKey('delete', () => {
      const cells = graph.getSelectedCells()
      if (cells.length) {
        graph.removeCells(cells)
      }
    })
    // 鼠标动态添加/删除小工具。
    graph.on('edge:mouseenter', ({ cell }) => {
      /**
       * EdgeTool
       * vertices 路径点工具,在路径点位置渲染一个小圆点,拖动小圆点修改路径点位置,双击小圆点删除路径点,在边上单击添加路径点。
       * segments 线段工具。在边的每条线段的中心渲染一个工具条,可以拖动工具条调整线段两端的路径点的位置。
       * boundary 根据边的包围盒渲染一个包围边的矩形。注意,该工具仅仅渲染一个矩形,不带任何交互。
       * button 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。
       * button-remove 在指定的位置处,渲染一个删除按钮,点击时删除对应的边。
       * source-arrowhead-和-target-arrowhead 在边的起点或终点渲染一个图形(默认是箭头),拖动该图形来修改边的起点或终点。
       * edge-editor 提供边上文本编辑功能。
       */
      cell.addTools([
        {
          name: 'vertices',
          args: {
            attrs: { fill: '#007acc' },
            // 移动路径点过程中的吸附半径。当路径点与邻近的路径点的某个坐标 (x, y) 距离在半径范围内时,将当前路径点的对应坐标 (x, y) 吸附到邻居路径的路径点。
            snapRadius: 20,
            // 在边上按下鼠标时,是否可以添加新的路径点。
            addable: false,
            // 是否可以通过双击移除路径点。
            removable: false,
            // 是否自动移除冗余的路径点。
            removeRedundancies: false,
            // 是否阻止工具上的鼠标事件冒泡到边视图上。阻止后鼠标与工具交互时将不会触发边的 mousedown、mousemove 和 mouseup 事件。
            stopPropagation: false
          }
        }
      ])
    })
    graph.on('edge:mouseleave', ({ cell }) => {
      cell.removeTools()
    })
  }
}