<template>
  <div :style="`height:${fieldMapHeight}`" class="fieldMapping">
    <svg
      ref="svg"
      version="1.1"
      xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      @input="$emit('input', $event)"
    >
      <foreignObject :width="tableWidth + 30" class="table">
        <body xmlns="http://www.w3.org/1999/xhtml" @contextmenu.prevent>
        <el-table ref="sourceTable" :data="val.source" border stripe>
          <el-table-column align="center" type="index" width="60"/>
          <el-table-column
            align="center"
            label="源字段名称"
            prop="fieldName"
            show-overflow-tooltip
          >
            <template slot-scope="scope">
              {{ scope.row.fieldName || scope.row.fieldName }}
            </template>
          </el-table-column>
          <el-table-column
            align="center"
            label="类型"
            prop="fieldType"
            show-overflow-tooltip
            width="100"
          >
            <template slot-scope="scope">
              <span>{{ scope.row.fieldType }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="port" width="20">
            <template slot-scope="scope">
              <div
                :style="
                    isSafari ? 'left:10px;cursor:crosshair' : 'cursor:crosshair'
                  "
                class="port start"
                draggable="true"
                @dragstart.stop="dragStart($event, scope.row)"
                @drag.stop="dragGing($event, scope.row)"
                @dragend.stop="dragEnd($event, scope.row)"
              />
            </template>
          </el-table-column>
        </el-table>
        </body>
      </foreignObject>
      <foreignObject :width="tableWidth" :x="tableX" class="table">
        <body xmlns="http://www.w3.org/1999/xhtml">
        <el-table ref="targetTable" :data="val.target" border stripe>
          <el-table-column prop="port" width="20">
            <template slot-scope="scope">
              <div
                class="port end"
                @dragover.prevent="dragOver($event)"
                @drop.prevent="dragDrop($event, scope.row)"
              />
            </template>
          </el-table-column>
          <el-table-column align="center" type="index" width="60"/>
          <el-table-column
            align="center"
            label="目标字段名称"
            prop="fieldName"
            show-overflow-tooltip
          />
          <el-table-column
            align="center"
            label="类型"
            prop="fieldType"
            show-overflow-tooltip
            width="100"
          />
        </el-table>
        </body>
      </foreignObject>
      <foreignObject :x="menuX" class="menu" height="100" width="80">
        <body xmlns="http://www.w3.org/1999/xhtml">
        <div @click="mapByName">同名映射</div>
        <div @click="unmap">取消映射</div>
        </body>
      </foreignObject>
      <MyLine v-show="dragingFlag" :coordinate="dragLineData"/>
      <MyTriangle v-show="dragingFlag" :coordinate="dragLineData"/>

      <g>
        <MyLine
          v-for="(item, index) in allLineData"
          :key="'line' + index"
          :coordinate="item"
          @contextmenu.native.prevent="rightClickLine($event, item)"
        />
      </g>

      <MyTriangle
        v-for="(item, index) in allLineData"
        :key="'triangle' + index"
        :coordinate="item"
      />
    </svg>

    <PopMenu ref="popMenu" :menus="nodeMenus"/>
  </div>
</template>

<script>
import MyLine from './components/line'
import MyTriangle from './components/triangle'
import PopMenu from '@/components/PopMenu'

export default {
  name: 'FieldMapping',
  components: {
    MyLine,
    MyTriangle,
    PopMenu
  },
  props: {
    value: {
      type: Object,
      default: () => {
      }
    }
  },
  data() {
    return {
      isSafari: false,
      tableWidth: 300,
      tableX: 0,
      menuX: 1400,
      startXY: {
        x: 0,
        y: 0
      },
      dragStartRow: {},
      dragEndRow: {},
      dragingFlag: false,
      dragLineData: {
        x1: 0,
        y1: 0,
        x2: 0,
        y2: 0
      },
      allLineData: [],

      nodeMenus: [],
      clickedLine: {},
      isIniting: true
    }
  },
  computed: {
    val: function() {
      return this.value
    },
    fieldMapHeight: function() {
      const mapLength =
        this.value.source.length + 1 > this.value.target.length
          ? this.value.source.length + 1
          : this.value.target.length
      return `${mapLength * 40 + 60}px`
    }
  },
  methods: {
    init() {
      this.getRowsCoordinate()
      this.initConnect()
      this.autoTypeSet()
      this.isIniting = false
    },
    initLine() {
      this.getRowsCoordinate()
      this.initConnect()
    },
    getRowsCoordinate() {
      const svg = this.$refs.svg.getBoundingClientRect()
      this.val.source.forEach((el, index) => {
        el.coordinate = {
          x: (svg.width - 80) / 3 + 31,
          y: (index + 1) * 44 + 26 //设置绘制箭头连接重点的坐标
        }
      })
      this.val.target.forEach((el, index) => {
        el.coordinate = {
          x: ((svg.width - 80) / 3) * 2 - 32,
          y: (index + 1) * 44 + 26 //展示绘制箭头连接重点的坐标
        }
      })
      this.tableWidth = (svg.width - 80) / 3 + 40
      this.tableX = ((svg.width - 80) / 3) * 2 - 40
      this.menuX = svg.width - 80
      if (
        navigator.userAgent.indexOf('Safari') > -1 &&
        navigator.userAgent.indexOf('Chrome') < 0
      ) {
        this.isSafari = true
      }
    },
    initConnect() {
      this.allLineData = []
      for (var el of this.val.source) {
        if (el.connectTo !== '') {
          for (var ele of this.val.target) {
            if (el.connectTo === ele.fieldId) {
              this.addLine(el, ele)
              break
            }
          }
        }
      }
    },

    addLine(startRow, endRow) {
      let newLine = {
        id: this.allLineData.length + 1,
        starFieldId: startRow.fieldId,
        endFieldId: endRow.fieldId,
        x1: startRow.coordinate.x,
        y1: startRow.coordinate.y,
        x2: endRow.coordinate.x,
        y2: endRow.coordinate.y
      }
      this.allLineData.push(newLine)
      if (this.isIniting == false) {
        this.$emit('addFieldMapping', newLine)
      }
    },
    delLine() {
      if (!this.clickedLine.starFieldId) {
        return
      }
      for (var el of this.val.source) {
        if (el.fieldId === this.clickedLine.starFieldId) {
          el.connectTo = ''
          break
        }
      }
      this.allLineData.splice(this.allLineData.indexOf(this.clickedLine), 1)
      this.$emit('delFieldMapping', this.clickedLine)
    },
    rightClickLine(event, line) {
      this.clickedLine = line
      this.nodeMenus = [{ val: '删除', func: this.delLine, params: [] }]
      this.$refs.popMenu.open({
        x: event.clientX,
        y: event.clientY
      })
    },

    dragStart(e, row) {
      var img = new Image()
      e.dataTransfer.setDragImage(img, 8, 3)
      e.dataTransfer.setData('port', row)

      this.dragStartRow = row
      this.startXY = {
        x: e.pageX,
        y: e.pageY
      }
      this.dragLineData.x1 = row.coordinate.x
      this.dragLineData.y1 = row.coordinate.y
    },
    dragGing(e, row) {
      this.dragingFlag = true
      this.dragLineData.x2 =
        this.dragStartRow.coordinate.x + e.pageX - this.startXY.x - 17
      this.dragLineData.y2 =
        this.dragStartRow.coordinate.y + e.pageY - this.startXY.y
    },
    dragEnd(e, row) {
      this.dragingFlag = false
    },
    dragOver(e) {
    },
    dragDrop(e, row) {
      var flag = false
      this.val.source.forEach((el) => {
        if (el.connectTo === row.fieldId) {
          flag = true
          return false
        }
      })

      this.dragEndRow = row
      this.dragStartRow.connectTo = row.fieldId
      this.addLine(this.dragStartRow, this.dragEndRow)
    },

    mapByName() {
      for (var el of this.val.source) {
        el.connectTo = ''
        for (var ele of this.val.target) {
          if (el.fieldId === ele.fieldId) {
            el.connectTo = ele.fieldId
            break
          }
        }
      }
      this.initConnect()
    },
    mapByRow() {
      this.val.source.forEach((el, index) => {
        el.connectTo = ''
        if (this.val.target[index]) {
          el.connectTo = this.val.target[index].fieldId
        }
      })
      this.initConnect()
    },
    unmap() {
      this.val.source.forEach((el) => {
        el.connectTo = ''
      })
      this.allLineData = []
    },
    autoTypeSet() {
      var copySourceConnet = []
      var copySourceUnConnet = []
      var copyTarget = []
      var namesStr = []
      this.val.source.forEach((el) => {
        if (el.connectTo === '') {
          copySourceUnConnet.push(el)
        } else {
          copySourceConnet.push(el)
        }
      })
      copySourceConnet.forEach((el) => {
        for (var ele of this.val.target) {
          if (el.connectTo === ele.fieldId) {
            copyTarget.push(ele)
            namesStr.push(ele.fieldId)
            break
          }
        }
      })
      this.val.target.forEach((el) => {
        if (namesStr.indexOf(el.fieldId) === -1) {
          copyTarget.push(el)
        }
      })
      copySourceConnet.push(...copySourceUnConnet)
      this.val.source = copySourceConnet
      this.val.target = copyTarget
      this.initLine()
    }
  }
}
</script>

<style lang="scss" scoped>
.fieldMapping {
  width: 100%;
  height: 100%;

  svg {
    width: 100%;
    height: 100%;
    background: transparent;
  }

  body {
    background: transparent;
  }

  .table {
    width: calc((100% - 80px) / 3 + 40px);
    height: 100%;
  }

  .menu {
    width: 80px;
    height: 100%;
    text-align: center;
    background: transparent;

    div {
      color: #9d9fa9;
      cursor: pointer;

      &:hover {
        color: #000;
      }
    }
  }

  .port {
    position: relative;
    left: -9px;
    width: 18px;
    height: 18px;
    background: #3d4ae4;
    border-radius: 50%;

    &::after {
      position: absolute;
      top: 5px;
      left: 5px;
      content: "";
      width: 8px;
      height: 8px;
      background: #fff;
      border-radius: 50%;
    }

    &:hover {
      background: #646ee0;
    }
  }

  ::v-deep .el-table tr {
    height: 36px;
  }
}
</style>
