<template>
  <a-modal
    :visible="visible"
    :width="1200"
    destroy-on-close
    :title="mode === 'flow' ? '查看流程图' : '从流程图选择'"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <a-card :class="$style.chart" size="small">
      <div :class="$style.wrapper">
        <div v-if="svgFlowInfo">
          <!-- eslint-disable-next-line vue/no-v-html -->
          <div ref="svg" :class="$style.svg" v-html="svgFlowInfo" />
        </div>
        <div v-else :class="$style.spin"><a-spin :spinning="spinning"/></div>
      </div>
    </a-card>
  </a-modal>
</template>

<script>
import axios from '@/common/services/axios-instance'
import { Message } from 'ant-design-vue'
import components from './_import-components/sd-flowchart-action-import'
function addClassName(node, className) {
  if (node && node.className.baseVal.split(' ').indexOf(className) === -1)
    node.setAttribute('class', node.getAttribute('class') + ' ' + className)
}
function removeClassName(node, className) {
  const classes = node.getAttribute('class') || ''
  node.setAttribute(
    'class',
    classes
      .split(' ')
      .filter((str) => str !== className)
      .join(' ')
  )
}
export default {
  name: 'SdFlowchartAction',
  metaInfo: {
    title: 'SdFlowchartAction',
  },
  components,
  props: {
    mode: {
      type: String,
      default: 'VIEW',
    },
    checkedList: {
      type: Array,
      default: () => [],
    },
    options: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      svgFlowInfo: undefined,
      nodePositions: [],
      spinning: true,
      visible: false,
      flowId: '',
    }
  },
  methods: {
    handleOk() {
      this.$emit(
        'selectNode',
        this.nodePositions.filter((node) => node.selected).map((m) => m.id)
      )
      this.visible = false
    },
    select(node, svgNode) {
      node.selected = !node.selected
      if (node.selected) {
        addClassName(svgNode, 'sd-current')
      } else {
        removeClassName(svgNode, 'sd-current')
      }
      if (this.mode === 'line') this.handleArrows(node.selected ? 'add' : 'remove', svgNode)
    },
    handleArrows(type, svgNode) {
      const svgRoot = this.$refs.svg.querySelector('svg')
      svgNode
        .querySelector('path')
        .getAttribute('marker-end')
        .match(/\((.+?)\)/g)
      svgNode = svgRoot.querySelector(`${RegExp.$1.replace(/'/g, '').replace(/"/g, '')} path`)
      if (type === 'add') addClassName(svgNode, 'sd-current')
      else removeClassName(svgNode, 'sd-current')
    },
    getSvgFlowInfo() {
      return axios(`api/framework/v1/process-prop/svg?flowId=${this.flowId}`)
        .then((res) => {
          this.svgFlowInfo = res.data
          this.$nextTick(this.updateFlowChart)
        })
        .catch((e) => {
          Message.error('获取流程图失败')
        })
        .finally(() => {
          this.spinning = false
        })
    },
    // 更新流程图底图相关信息
    updateFlowChart() {
      // 计算每个节点的位置信息
      const nodePositions = []
      const svgRoot = this.$refs.svg.querySelector('svg')
      svgRoot
        .querySelectorAll('.stencils .children >g,.stencils .edge >g, marker >path')
        .forEach((node) => {
          removeClassName(node, 'sd-current')
        })
      // 防止流程图过长超出背景图
      document.querySelector(`.${this.$style.chart}`).style.minWidth =
        svgRoot.getAttribute('width') + 'px'
      const svgPosition = svgRoot.getBoundingClientRect()
      svgRoot
        .querySelectorAll(this.mode === 'line' ? `.stencils .edge>g` : `.stencils .children>g`)
        .forEach((node) => {
          const position = node.getBoundingClientRect()
          const id = node.getAttribute('stepid')
          const currentNode = {
            id,
            x: position.left - svgPosition.left,
            y: position.top - svgPosition.top,
            width: position.width,
            height: position.height,
            selected: this.checkedList.indexOf(id) > -1,
          }
          if (currentNode.selected && this.mode !== 'flow') {
            addClassName(node, 'sd-current')
            if (this.mode === 'line') this.handleArrows('add', node)
          }
          nodePositions.push(currentNode)
          const inParts = this.options.find(
            (item) => (this.mode === 'node' ? item.stepId : item.id) === currentNode.id
          )
          if (inParts && this.mode !== 'flow') {
            node.addEventListener('click', (e) => {
              this.select(currentNode, node)
            })
            addClassName(node, 'sd-nodeclickable')
          } else addClassName(node, 'sd-nodeclickdisable')
        })
      this.nodePositions = nodePositions
    },
    open() {
      this.visible = true
      this.getSvgFlowInfo()
    },
    handleCancel() {
      this.svgFlowInfo = ''
      this.visible = false
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
$default-color: #f3f3f3;
$default-deep-color: #d7d7d7;
$check-icon-size: 30px;
.spin {
  text-align: center;
}
.svg {
  :global marker {
    path {
      fill: $default-deep-color;
      stroke: $default-deep-color;
    }
    path.sd-current {
      fill: $success-color;
      stroke: $success-color;
    }
  }
  :global .stencils {
    .children {
      circle,
      rect {
        fill: $default-color;
        stroke: $default-deep-color;
      }

      .sd-current {
        circle,
        rect {
          stroke: $success-color;
        }
      }
    }
    .edge {
      path {
        stroke: $default-deep-color;
      }
      .sd-current {
        path {
          stroke: $success-color;
        }
      }
    }
  }
  :global(.sd-nodeclickable) {
    cursor: pointer;
  }
  :global(.sd-nodeclickdisable) {
    cursor: not-allowed;
  }
}
.chart {
  position: relative;
}
.step-tip-wrapper {
  font-size: $font-size-sm;
  .step-info {
    p {
      max-width: 300px;
      margin-bottom: 5px;
    }
    .countersign-info {
      cursor: pointer;
      .recipient-dept {
        color: $primary-color;
      }
    }
  }
  .brackets::before {
    content: '(';
  }
  .brackets::after {
    content: ')';
  }
  .brackets:empty {
    display: none;
  }
}
.flow-chart-modal :global(.ant-modal-body) {
  padding: 0;
}
.point {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  .check-icon {
    font-size: $check-icon-size;
    color: $green-5;
  }
}
</style>
