<template>
  <div>
    <div class="m-2">
      <!--      <svg class="icon" aria-hidden="true" style="height: 25px;width: 40px">-->
      <!--        <use xlink:href="#icon-shangchuan"></use>-->
      <!--      </svg>-->
      <!--      <el-button type='primary' @click='impXml' plain :icon='Upload'>导入</el-button>-->
      <!--      <el-button type='primary' @click='expXML' plain :icon='Download'>导出XML</el-button>-->
      <a-button class="mr-2" type="primary" @click="expSVG">导出SVG</a-button>
      <a-button class="mr-2" type="primary" @click="codeShow">代码预览</a-button>
      <a-button class="mr-2" type="primary" @click="setZoom(0)">缩小</a-button>
      <a-button class="mr-2" type="primary" @click="setZoom(1)">还原居中</a-button>
      <a-button class="mr-2" type="primary" @click="setZoom(2)">放大</a-button>

      <span style="color: red; margin-left: 10px">注：双击节点或连线编辑信息</span>
    </div>
    <div class="containers">
      <div class="canvas" ref="canvasRef" style="height: 1000px" />
      <NodeModal @register="registerNodeModal" @close="closeNodeModal" />
    </div>
    <CodeModal @register="registerCodeModal" />
  </div>
</template>

<script lang="ts" setup>
  // import BpmnModeler from 'bpmn-js/lib/Modeler'
  import { defineExpose, onMounted, reactive, ref, toRefs } from 'vue';
  import 'bpmn-js/dist/assets/diagram-js.css'; // 左边工具栏以及编辑节点的样式
  import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
  import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
  import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
  // import customModule from './custom';
  import CustomModeler from './customModeler';
  import NodeModal from './modal.vue';
  import CodeModal from './code.vue';
  import { putNodeNum, putLineNum, getLineNum, getNodeNum } from './customModeler/custom/store';
  import { useRoute } from 'vue-router';
  import { useModal } from '/@/components/Modal';
  import { nanoid } from 'nanoid';
  import { downloadByUrl } from '/@/utils/file/download';

  const route = useRoute();

  const canvasRef = ref();
  const [registerCodeModal, { openModal: openCodeModal }] = useModal();
  const [registerNodeModal, { openModal: openNodeModal }] = useModal();

  const state = reactive({
    data: [] as any,
    bpmnModeler: {} as any,
    numFlag: 'x' as any,
    zoom: 1,
  });

  const props = defineProps({
    prxml: String,
  });

  const { bpmnModeler, zoom } = toRefs(state);

  onMounted(async () => {
    if (route.query?.uuid) {
      state.numFlag = route.query?.uuid;
    } else if (route.query?.id) {
      state.numFlag = route.query?.id;
    }
    console.log('numFlag2:' + state.numFlag);
    bpmnModeler.value = new CustomModeler({
      container: canvasRef.value,
      additionalModules: [
        {
          __init__: ['labelEditingProvider'],
          labelEditingProvider: ['value', null],
        },
      ],
    });

    bpmnModeler.value.get('keyboard').bind(document);

    if (props.prxml) {
      await bpmnModeler.value.importXML(props.prxml, (err: any) => {
        if (err) {
          console.error(err);
        } else {
          console.log('ok');
        }
      });
    } else {
      await bpmnModeler.value.importXML(defxml, (err: any) => {
        if (err) {
          console.error(err);
        } else {
          console.log('ok');
        }
      });
    }
    addModelerListener();
    addEventBusListener();
  });

  const addModelerListener = () => {
    // const bpmnjs = this.bpmnModeler
    // const that = this
    // 这里我是用了一个forEach给modeler上添加要绑定的事件
    const events = [
      'shape.added',
      'shape.move.end',
      'shape.removed',
      'connection.added',
      'connect.end',
      'connect.move',
    ];
    events.forEach(function (event) {
      bpmnModeler.value.on(event, e => {
        const elementRegistry = bpmnModeler.value.get('elementRegistry');
        const shape = e.element ? elementRegistry.get(e.element.id) : e.shape;
        if (event == 'shape.added') {
          if (
            e.element.id.substring(0, 1) == 'N' &&
            e.element.id.substring(0, 2) !== 'NS' &&
            e.element.id.substring(0, 2) !== 'NE'
          ) {
            // shape.name="审批节点"
            putNodeNum(state.numFlag, e.element.id.substring(1) - 0);
          }
        } else if (event == 'connection.added') {
          // console.log("创建了线段");
          // console.log(e.element);
          if (e.element.id.substring(0, 1) == 'L') {
            putLineNum(state.numFlag, e.element.id.substring(1) - 0);
          } else {
            //如果更新Line的ID?
            // bpmnModeler.value.get('modeling').updateProperties(e.element, {
            // 	id: "L"+(getLineNum(state.numFlag)-0+1),
            // 	// data:JSON.stringify(data),
            // });
            // putLineNum(state.numFlag, (getLineNum(state.numFlag)-0+1));
          }
        }
      });
    });
  };

  let currNode = {};
  // let lastNum=10;

  const addEventBusListener = () => {
    const eventBus = bpmnModeler.value.get('eventBus'); // 需要使用eventBus
    const eventTypes = ['element.dblclick']; // 需要监听的事件集合
    eventTypes.forEach(function (eventType) {
      eventBus.on(eventType, function (e) {
        if (!e || e.element.type == 'bpmn:Process') return;

        const elementRegistry = bpmnModeler.value.get('elementRegistry');
        const shape = elementRegistry.get(e.element.id); // 传递id进去

        // if(e.element.id.substring(0,1)!="N"){
        //
        // 	// bpmnModeler.value.get('modeling').updateProperties(shape,{
        // 	// 	name: '我哎你'
        // 	// })
        //
        // 	// // e.element.id="N"+(++lastNum);
        // 	// shape.id="N"+(++lastNum);
        // 	++lastNum;
        // 	shape.id="N"+lastNum;
        // 	shape.businessObject.id="N"+lastNum;
        //
        // 	console.log('新增了shape');
        // 	// console.log(e.element.id);
        // 	// 展示新增图形的属性
        // }

        console.log('双击了shape');
        console.log(shape);
        openNodeModal(true, {
          record: shape,
        });
        currNode = shape;

        // openNodeModal(shape);

        // console.log(shape.businessObject.id);
        // shape.businessObject.name='李四';
        // bpmnModeler.value.get('modeling').updateProperties(shape,{
        // 	name: '我是修改后的Task名称'
        // })

        // this.getModeling().updateProperties(this.getShape(), {
        // 	[modelName]: multiple ? [newElement] : newElement,
        // });
        console.log(shape); // {Shape}
        // console.log(e.element) // {Shape}
        // console.log(JSON.stringify(shape)===JSON.stringify(e.element)) // true
      });
    });
  };

  const closeNodeModal = (data: any) => {
    if (data.conds) {
      bpmnModeler.value.get('modeling').updateProperties(currNode, {
        name: data.name,
        conds: data.conds,
      });
    } else {
      bpmnModeler.value.get('modeling').updateProperties(currNode, {
        name: data.name,
        hamen: data.hamen,
        flway: data.flway,
        // data:JSON.stringify(data),
      });
    }
  };

  const getXml = async () => {
    let backXml = '';
    await bpmnModeler.value.saveXML({ format: true }).then(res => {
      backXml = res.xml;
    });
    return backXml;
  };

  const setZoom = async (num: Number) => {
    if (num == 2) {
      zoom.value = Math.floor(zoom.value * 100 + 0.1 * 100) / 100;
    } else if (num == 0) {
      zoom.value = Math.floor(zoom.value * 100 - 0.1 * 100) / 100;
    } else {
      zoom.value = 1;
      bpmnModeler.value.get('canvas').zoom('fit-viewport', 'auto');
      return;
    }
    bpmnModeler.value.get('canvas').zoom(zoom.value);
  };

  defineExpose({ getXml });

  const defxml =
    '<?xml version="1.0" encoding="UTF-8"?>\n' +
    '<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:activiti="http://activiti.org/bpmn" id="sample-diagram" targetNamespace="http://activiti.org/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">\n' +
    '  <bpmn2:process id="Process_1" name="1" isExecutable="true">\n' +
    '    <bpmn2:startEvent id="NS" name="开始节点">\n' +
    '      <bpmn2:outgoing>L1</bpmn2:outgoing>\n' +
    '    </bpmn2:startEvent>\n' +
    '    <bpmn2:sequenceFlow id="L1" sourceRef="NS" targetRef="N1" />\n' +
    '    <bpmn2:endEvent id="NE" name="结束节点">\n' +
    '      <bpmn2:incoming>L2</bpmn2:incoming>\n' +
    '    </bpmn2:endEvent>\n' +
    '    <bpmn2:userTask id="N1" name="起草节点" activiti:assignee="l4" activiti:candidateUsers="">\n' +
    '      <bpmn2:documentation>起草节点，表单数据一般从绑定的表单提取</bpmn2:documentation>\n' +
    '      <bpmn2:extensionElements>\n' +
    '        <activiti:formProperty id="userid" type="string" />\n' +
    '        <activiti:formProperty id="money" type="int" />\n' +
    '        <activiti:properties>\n' +
    '          <activiti:property name="编辑" value="edit" />\n' +
    '          <activiti:property name="撤回" value="back" />\n' +
    '          <activiti:property name="提交" value="commit" />\n' +
    '        </activiti:properties>\n' +
    '      </bpmn2:extensionElements>\n' +
    '      <bpmn2:incoming>L1</bpmn2:incoming>\n' +
    '      <bpmn2:outgoing>L2</bpmn2:outgoing>\n' +
    '    </bpmn2:userTask>\n' +
    '    <bpmn2:sequenceFlow id="L2" sourceRef="N1" targetRef="NE" />\n' +
    '  </bpmn2:process>\n' +
    '  <bpmndi:BPMNDiagram id="BPMNDiagram_1">\n' +
    '    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">\n' +
    '      <bpmndi:BPMNEdge id="Flow_1u6pmzo_di" bpmnElement="L1">\n' +
    '        <di:waypoint x="360" y="78" />\n' +
    '        <di:waypoint x="360" y="160" />\n' +
    '      </bpmndi:BPMNEdge>\n' +
    '      <bpmndi:BPMNEdge id="Flow_0rj5mf6_di" bpmnElement="L2">\n' +
    '        <di:waypoint x="360" y="240" />\n' +
    '        <di:waypoint x="360" y="452" />\n' +
    '      </bpmndi:BPMNEdge>\n' +
    '      <bpmndi:BPMNShape id="Event_0byql27_di" bpmnElement="NS">\n' +
    '        <dc:Bounds x="342" y="42" width="36" height="36" />\n' +
    '        <bpmndi:BPMNLabel>\n' +
    '          <dc:Bounds x="339" y="12" width="43" height="14" />\n' +
    '        </bpmndi:BPMNLabel>\n' +
    '      </bpmndi:BPMNShape>\n' +
    '      <bpmndi:BPMNShape id="Activity_0g48n8q_di" bpmnElement="N1">\n' +
    '        <dc:Bounds x="310" y="160" width="100" height="80" />\n' +
    '      </bpmndi:BPMNShape>\n' +
    '      <bpmndi:BPMNShape id="Event_1h4oob7_di" bpmnElement="NE">\n' +
    '        <dc:Bounds x="342" y="452" width="36" height="36" />\n' +
    '        <bpmndi:BPMNLabel>\n' +
    '          <dc:Bounds x="339" y="495" width="43" height="14" />\n' +
    '        </bpmndi:BPMNLabel>\n' +
    '      </bpmndi:BPMNShape>\n' +
    '    </bpmndi:BPMNPlane>\n' +
    '  </bpmndi:BPMNDiagram>\n' +
    '</bpmn2:definitions>\n';

  const impXml = () => {};

  const expXML = async () => {
    await bpmnModeler.value.saveXML({ format: true }).then(res => {
      download(res.xml, 'process', 'bpmn');
    });
  };

  const expSVG = async () => {
    await bpmnModeler.value.saveSVG({ format: true }).then(res => {
      download(res.svg, 'process', 'svg');
    });
  };

  //文本下载
  const download = (data: string, filename: string, type: string): void => {
    const blob = new Blob([data]);
    // const tempLink = document.createElement('a'); // 创建a标签
    const url = window.URL.createObjectURL(blob); // 创建下载的链接
    // //filename
    // const fileName = `${filename}.${type}`;
    // tempLink.href = href;
    // tempLink.target = '_blank';
    // tempLink.download = fileName;
    // document.body.appendChild(tempLink);
    // tempLink.click(); // 点击下载
    // document.body.removeChild(tempLink); // 下载完成移除元素
    // window.URL.revokeObjectURL(href); // 释放掉blob对象
    downloadByUrl({
      url,
      fileName: `${filename}.${type}`,
    });
    window.URL.revokeObjectURL(url);
  };

  const codeShow = async () => {
    await bpmnModeler.value.saveXML({ format: true }).then(res => {
      openCodeModal(true, {
        record: res.xml,
      });
    });
  };
</script>

<style scoped>
  .containers {
    position: absolute;
    background-color: #ffffff;
    width: 100%;
    height: 100%;
    background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+')
      repeat !important;
  }

  .dark .containers {
    background-color: #666 !important;
  }

  .canvas {
    width: 100%;
    height: 100%;
  }

  .panel {
    position: absolute;
    right: 0;
    top: 0;
    width: 300px;
  }
  ::v-deep(.djs-palette) {
    width: 96px;
  }
  ::v-deep(.djs-palette-entries div[data-group='create']),
  ::v-deep(.djs-context-pad.open div[data-group='model']) {
    display: none;
  }
</style>
