<template>
  <div class="canvas-wrapper">
    <div class="canvas-container">

      <div class="flow-canvas" id="canvas" @dragover="handleDragOver" @dragenter="handleDragEnter" @drop="handleDrag">
        <flow-legend v-for="item in nodes" :key="item.id" :node="item" :active="operationItem.type === item.type && operationItem.id === item.id">
        </flow-legend>
      </div>

    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import legend from './legend.vue'
import { clearActiveConnection, validateConnection } from './connectionUtil.js'
import util from '@src/common/util.js'

export default {
  computed: mapGetters({
    nodes: 'workflowNodes',
    workflowNode: 'workflowNode',
    operationItem: 'operationItem',
    createNodeType: 'createNodeType',
    currentNode: 'currentNode',
    workflowType: 'workflowType'
  }),
  methods: {
    handleDragOver(ev) {
      // 拖拽元素在目标元素头上移动的时候
      ev.preventDefault()
      return true
    },
    handleDragEnter(ev) {
      // 拖拽元素进入目标元素头上的时候
      return true
    },
    async handleDrag(ev) {
      let newNodeID = this.nodes.length + 1
      while (this.nodes.map(val => parseInt(val.id)).includes(newNodeID)) {
        newNodeID = newNodeID + 1
      }
      const legendType = this.createNodeType

      const legendId = newNodeID.toString()

      const legendName = legendType === 'Node' ? '新建的步骤' : '新建的动作'

      clearActiveConnection(this.operationItem, window._jsPlumbInstance)

      const nodeInfo = {
        id: legendId,
        name: legendName,
        left: ev.offsetX,
        top: ev.offsetY,
        type: legendType
      }

      await this.$store.dispatch('addNode', nodeInfo)

      await this.$store.dispatch('changeOperationItem', {
        id: legendId,
        type: legendType
      })
    },
    async loadLibrary () {
      if (typeof window.jsPlumbInstance === 'undefined') {
        try {
          console.log(util)
          await util.loadJS('./lib/jsplumb/js/jsplumb.min.js')
        } catch (e) {
          console.error('jsplumb.min.js is missing', e.toString())
          return null
        }
      }
      return window.jsPlumbInstance
    }
  },
  async mounted() {
    await this.loadLibrary()
    let self = this
    window.jsPlumb.ready(() => {
      let instance = window._jsPlumbInstance = window.jsPlumb.getInstance({
        Endpoint: ['Dot', { radius: 2 }],
        Connector: self.$store.state.workFlow.connectorStyle || 'Flowchart', //  连接线的样式种类有'Bezier''Flowchart','StateMachine','Straight'
        HoverPaintStyle: { stroke: '#1e8151', strokeWidth: 2 },
        ConnectionsDetachable: false,
        ConnectionOverlays: [
          ['Arrow', { location: 1, id: 'arrow', length: 14, foldback: 0.8 }],
          ['Label', { label: '', id: 'label', cssClass: 'aLabel' }]
        ],
        Container: 'canvas'
      }); let isConnectionDrag = false
      instance.registerConnectionType('basic', { anchor: 'Continuous' })

      instance.bind('click', (connection) => {
        let { sourceId, targetId } = connection

        sourceId = sourceId.slice(6)
        targetId = targetId.slice(6)

        clearActiveConnection(self.operationItem, instance)

        instance.batch(() => {
          self.$store.dispatch('changeOperationItem', {
            type: 'connection',
            sourceId: sourceId,
            targetId: targetId
          })
        })

        connection.addClass('active-line')
      })

      instance.bind('connectionDrag', () => {
        isConnectionDrag = true
      })

      instance.bind('connection', (info) => {
        if (!isConnectionDrag) {
          return
        }

        let { sourceId, targetId } = info.connection

        sourceId = sourceId.slice(6)
        targetId = targetId.slice(6)

        const sourceNode = self.workflowNode(sourceId)
        const targetNode = self.workflowNode(targetId)
        // 验证连线是否符合规则。

        const validateResult = validateConnection(sourceNode, targetNode)

        if (!validateResult.isValidated) {
          instance.deleteConnection(info.connection)
          util.showErrorMessage(validateResult.message)
          return
        }

        const result = self.$store.dispatch('addConnection', {
          sourceId,
          targetId
        })

        result.then(() => {
          info.connection.getOverlay('label').setLabel('')
        }).finally(() => {
          isConnectionDrag = false
        })
      })

      this.$emit('canvas-initialized', window.jsPlumb)
    })

    document.addEventListener('keydown', (e) => {
      if (![37, 38, 39, 40].includes(e.keyCode) ||
          !['StartNode', 'Node', 'ActionNode', 'EndNode'].includes(this.operationItem.type) ||
          ['INPUT', 'TEXTAREA'].includes(e.target.tagName)) {
        return
      }

      const legendEl = document.getElementById('legend' + this.currentNode.id)

      const step = 1

      let left = this.currentNode.left

      let top = this.currentNode.top
      // 下
      if (e.keyCode === 40) {
        top = top + step
      }
      // 右
      if (e.keyCode === 39) {
        left = left + step
      }
      // 上
      if (e.keyCode === 38) {
        top = top - step
      }
      // 左
      if (e.keyCode === 37) {
        left = left - step
      }

      legendEl.style.top = top + 'px'
      legendEl.style.left = left + 'px'
      this.$store.dispatch('movePosition', {
        id: this.currentNode.id,
        top,
        left
      })
      window._jsPlumbInstance.repaintEverything()
    }, false)
  },
  components: {
    'flow-legend': legend
  }
}
</script>

<style>
</style>
