<template>
  <div>
    <div class="jee-bpm-graphic-containers">
      <div class="jee-bpm-graphic-canvas" :id="containerId"></div>
    </div>
    <bpm-node-info-modal @register="registerModal" @notify="handleModalVisible"></bpm-node-info-modal>
  </div>
</template>

<script>
  import { watch, ref, onMounted } from 'vue';
  import { defHttp } from '/@/utils/http/axios';
  import BpmNodeInfoModal from './BpmNodeInfoModal.vue';
  import { useModal } from '/@/components/Modal';
  import inherits from 'inherits';
  import Viewer from 'bpmn-js/lib/Viewer';
  import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
  import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
  import { append as svgAppend, attr as svgAttr, create as svgCreate } from 'tiny-svg';
  import { query as domQuery } from 'min-dom';
  function CustomViewer(options) {
    Viewer.call(this, options);
  }
  inherits(CustomViewer, Viewer);
  CustomViewer.prototype._modules = [].concat(Viewer.prototype._modules, [ZoomScrollModule, MoveCanvasModule]);

  export default {
    name: 'BpmGraphic',
    props: {
      // 流程实例ID
      instanceId: {
        type: String,
        required: false,
      },
      center:{
        type: Boolean,
        default: false,
        required: false
      }
    },
    components: {
      BpmNodeInfoModal,
    },
    emits: ['task'],
    setup(props, { emit }) {
      const url = {
        getProcessInfo: '/act/designer/api/getProcessXmlByInstanceId',
        getInstanceInfo: '/act/task/getFlowMsgByProcInstId',
        getNodePositionInfo: '/act/task/getNodePositionInfo',
      };
      const [registerModal, { openModal, closeModal }] = useModal();
      const containerId = 'jee-bpm-graphic-canvas';
      let bpmViewer = null;
      onMounted(() => {
        newViewer();
      });

      let taskList = [];
      let currentTaskId = '';
      let currentNodeList = [];
      let historyNodeList = [];
      let historyLineList = [];
      let delayHandler = '';

      watch(
        () => props.instanceId,
        (val) => {
          if (val) {
            init();
          }
        },
        { immediate: true }
      );

      async function init() {
        let params = { processInstanceId: props.instanceId };
        // 1.加载流程设计xml
        let xml = await defHttp.get({ url: url.getProcessInfo, params }, { isTransformResponse: false });
        //console.log('xml', xml);
        // 2.加载流程实例信息
        let instanceInfo = await defHttp.get({ url: url.getInstanceInfo, params }, { isTransformResponse: false });
        //console.log('instanceInfo', instanceInfo);
        // 2.加载节点信息 NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
        let nodeInfo = await defHttp.get({ url: url.getNodePositionInfo, params }, { isTransformResponse: false });
        //console.log('nodeInfo', nodeInfo);
        if (nodeInfo.success) {
          taskList = nodeInfo.result.hisTasks;
          emit('task', taskList);
        }
        //  console.log('taskList', nodeInfo.result)
        try {
          // 3.解析流程实例信息
          if (instanceInfo.success) {
            historyNodeList = instanceInfo.result.highLightedActivitiIdList;
            currentNodeList = instanceInfo.result.runningActivitiIdList;
            historyLineList = instanceInfo.result.highLightedFlowIds;
          }
          // 4.绘制流程
          newViewer();
          const result = await bpmViewer.importXML(xml);
          const { warnings } = result;
          console.log('bpm graphic warnings', warnings);
          // 5.调整图片位置
          const canvas = bpmViewer.get('canvas');
          if(props.center == true){
            canvas.zoom('fit-viewport', true);
          }
          // 6.创建箭头标记
          createArrow();
          // 7.设置节点、线的颜色
          setColor();
          // 8.节点事件
          addEvent();
        } catch (err) {
          console.log(err.message, err.warnings);
        }
      }

      function setColor() {
        // access viewer components
        const canvas = bpmViewer.get('canvas');
        // 获取到全部节点
        const allShapes = bpmViewer.get('elementRegistry').getAll();
        //循环节点添加class
        allShapes.forEach((element) => {
          const shapeId = element.businessObject.id;
          // const shapeAttrs = element.businessObject.$attrs
          //console.info('123element', element)
          let type = element.type;
          if (type == 'bpmn:ExclusiveGateway' || type == 'bpmn:InclusiveGateway' || type == 'bpmn:ParallelGateway') {
            canvas.addMarker(shapeId, 'jee-bpm-gateway');
          }
          // add marker
          if (element.businessObject.$type != 'bpmn:Group') {
            if (element.businessObject.$type == 'bpmn:SequenceFlow') {
              if (historyLineList.includes(shapeId)) {
                canvas.addMarker(shapeId, 'jee-bpm-history-line');
              }
            } else {
              if (historyNodeList.includes(shapeId) && !currentNodeList.includes(shapeId)) {
                canvas.addMarker(shapeId, 'jee-bpm-history-node');
              }
              if (currentNodeList.includes(shapeId)) {
                canvas.addMarker(shapeId, 'jee-bpm-current-node');
              }
            }
          }
        });
      }

      // 自定义箭头标记-默认箭头是黑色的
      function createArrow() {
        const marker = svgCreate('marker');
        svgAttr(marker, {
          id: 'active-arrow',
          viewBox: '0 0 20 20',
          refX: '11',
          refY: '10',
          markerWidth: '10',
          markerHeight: '10',
          orient: 'auto',
          fill: '#408af1',
        });
        const path = svgCreate('path');
        svgAttr(path, {
          d: 'M 1 5 L 11 10 L 1 15 Z',
          style: 'stroke-width: 1px; stroke-linecap: round; stroke-dasharray: 10000, 1;',
        });
        const defs = domQuery('defs');
        svgAppend(marker, path);
        svgAppend(defs, marker);
      }

      //添加节点事件
      function addEvent() {
        const eventBus = bpmViewer.get('eventBus');
        eventBus.on('element.hover', (e) => {
          const { element } = e;
          if (!element.parent) {
            // 这里关闭modal
            delayClose();
            currentTaskId = '';
            //console.log('鼠标移至空白处', element);
            return;
          }
          if (!e || element.type === 'bpmn:Process') {
            return false;
          } else {
            let temp = element.id;
            let type = element.type;
            if (currentTaskId != temp && 'bpmn:UserTask' == type && historyNodeList.indexOf(temp) >= 0) {
              /**
               * 满足3个条件才弹框显示节点信息
               * 1.当前节点不是鼠标选中的节点，防止多次调用
               * 2.必须是任务节点
               * 3.必须是处理过的节点
               */
              currentTaskId = temp;
              //console.log('准备开启modal', e);
              showNodeInfo();
            }
          }
        });
      }

      function showNodeInfo() {
        closeModal();
        openModal(true, {
          dataList: taskList,
          taskId: currentTaskId,
        });
      }

      function handleModalVisible(flag) {
        //console.log('handleModalVisible', flag)
        if (flag == true) {
          clearTimeout(delayHandler);
        }
      }

      function delayClose() {
        //console.log('delayClose')
        delayHandler = setTimeout(() => {
          //console.log('准备关闭modal');
          if (currentTaskId) {
            showNodeInfo();
          } else {
            closeModal();
          }
        }, 500);
      }

      function newViewer() {
        if (bpmViewer == null) {
          let dom = document.getElementById(containerId);
          bpmViewer = new CustomViewer({
            container: dom,
          });
        }
      }

      return {
        registerModal,
        containerId,
        handleModalVisible,
      };
    },
  };
</script>

<style lang="less">
  .jee-bpm-graphic-containers {
    width: 100%;
    height: calc(100vh - 250px);
  }

  .jee-bpm-graphic-canvas {
    width: 100%;
    height: 100%;
  }
  .jee-bpm-graphic-canvas .bjs-powered-by {
    display: none;
  }
  /**网关样式*/
  .jee-bpm-gateway .djs-visual path {
    stroke: none !important;
  }

  /**走过的分支线样式 */
  .jee-bpm-history-line .djs-visual > :nth-child(1) {
    stroke: #408af1 !important;
  }
  .jee-bpm-history-line path {
    marker-end: url(#active-arrow) !important;
    stroke-width: 2px!important;
  }

  /**走过的节点样式 */
  .jee-bpm-history-node .djs-visual > :nth-child(1) {
    fill: #51a2f13b !important;
    stroke: #408af1 !important;
  }

  /**当前节点样式 */
  .jee-bpm-current-node .djs-visual > :nth-child(1) {
    fill: #f9ca6d !important;
    stroke: #cd9423 !important;
  }
  /*  .jee-bpm-current-node .djs-visual > text {
    fill: #fff !important;
  }*/
</style>
