/* eslint-disable global-require */
import React, { useState, useEffect, useRef } from 'react';
import { Button, Modal, notification, Spin, Tooltip, message } from 'antd';
import lodash from 'lodash';
import {
  SaveNodeChange,
  GetFlowNode,
  FlowNodeSave,
  DeleteFlowNode,
  DeleteFlowNodes,
} from '@/services/workflow/workflow';

import { ExclamationCircleOutlined, TrophyOutlined } from '@ant-design/icons';
import { Prompt } from 'react-router-dom';
import * as go from 'gojs';
import styles from '../workflow.less';
import NodeModal from './flowChartComponents/NodeModal';
import LineModal from './flowChartComponents/LineModal';
// import imgUrl from '@/assets/images/icons/closeBlue.png';
import nodeEnd from '@/assets/images/workFlow/nodeEnd.svg';
import nodeGeneral from '@/assets/images/workFlow/nodeGeneral.svg';
import nodeStart from '@/assets/images/workFlow/nodeStart.svg';
// import cc from '@/assets/images/workFlow/cc.png';
import gatewayCondition from '@/assets/images/workFlow/gatewayCondition.svg';
import gatewayParallel from '@/assets/images/workFlow/gatewayParallel.svg';
import gatewayJoin from '@/assets/images/workFlow/gatewayJoin.svg';
const { confirm } = Modal;
let diagram = null;
let myPaletteNode = null;
let myPaletteGateway = null;
let myPaletteSubprocess = null;
let myOverview = null;
const FlowChart = props => {
  const { flowData, flowID, chartLoading, leaveCallBack, msg, treeVisible } = props;
  const [visible, setVisible] = useState(false);
  const [lineVisible, setLineVisible] = useState(false);
  const [editMsg, setEditMsg] = useState({}); // 编辑节点的信息
  const [lineMsg, setLineMsg] = useState({});
  const [modalType, setModalType] = useState(''); // 存入弹窗是编辑还是新增
  const [LineKey, setLineKey] = useState(''); //  存入编辑线id
  const [nodeKey, setNodeKey] = useState(''); // 存入编辑节点的key
  const [DeleteNodes, setDeleteNodes] = useState([]); // 删除节点数组
  const [DeleteLines, setDeleteLines] = useState([]); // 删除线数组
  const [deleteLine, setDeleteLine] = useState(); // 删除的线id
  const [deleteNode, setDeleteNode] = useState(); // 删除的节点id
  const [AddNodes, setAddNodes] = useState([]); // 新增数组
  const [initFlowData, setInitFlowData] = useState({}); // 初始数据，用来比对是否有修改流程图
  const [currentFlowData, setCurrentFlowData] = useState({
    Nodes: [],
    Lines: [],
  }); // 组件内得流程图数据
  const [showLeaveTip, setShowLeaveTip] = useState(false); // 离开路由是否又提醒
  const [buttonLoading, setButtonLoading] = useState(); // 发布按钮保存loading
  const [flag, setFlag] = useState(0);
  const currentNode = useRef();
  const afterNodes = useRef(new Map([])); // 当前节点后所有节点
  const limitFinshNodes = useRef([new Set([])]);
  const objGo = go.GraphObject.make;
  useEffect(() => {
    if (treeVisible) {
      setVisible(false);
    }
  }, [treeVisible]);

  // 监听删除，给删除数组里添加删除id
  useEffect(() => {
    if (deleteLine) {
      setDeleteLines([...DeleteLines, deleteLine]);
    }
  }, [deleteLine]);
  useEffect(() => {
    if (deleteNode) {
      setDeleteNodes([...DeleteNodes, deleteNode]);
    }
  }, [deleteNode]);
  // 初始化
  useEffect(() => {
    // 初始化流程图
    init();
    initPalette();
    myOverview = objGo(go.Overview, 'myOverviewDiv', { observed: diagram });
    // 监听节点或线的删除事件
    diagram.addDiagramListener('SelectionDeleted', e => {
      let delNodes = [];
      let delLinks = [];
      e.subject.each(n => {
        if (n.data.LineId) {
          delLinks.push(n.data.LineId);
        }
        if (n.data.ActivityId) {
          delNodes.push(n.data.ActivityId);
        }

        // 如果删除得节点不是新增得就给id放入到删除节点数组中
        if (n.data.NodeId && !AddNodes.some(item => item === n.data.NodeId)) {
          setTimeout(() => {
            setDeleteNode(n.data.NodeId);
          }, 0);
        }
        if (n.data.LineKey) {
          setTimeout(() => {
            setDeleteLine(n.data.LineId);
          }, 0);
        }
      });
      if (delNodes.length === 0) {
        return;
      }
      DeleteFlowNodes({ ActivityIds: delNodes, LineIds: delLinks }).then(res => {
        if (res.code === 0) {
          message.success('删除成功 ');
        } else {
          message.error({
            content: <div style={{ whiteSpace: 'pre-line', textAlign: 'justify' }}>{res.msg}</div>,
          });
        }
      });
      console.log(delNodes, delLinks, 'fffff');
    });
    // 监听节点或线的删除前事件
    diagram.commandHandler.canDeleteSelection = () =>
      // 用例获取选中的节点或线
      diagram.selection.all(e => {
        // 判断是否存在不允许删除的节点或线
        showDeleteConfirm(e.data);
        return false;
      });
    // 监听线,连接线的时候加上text属性
    diagram.addDiagramListener('LinkDrawn', e => {
      // e.subject.data.text = '';
      e.subject.data.lineDetail = JSON.stringify(e.subject.data);
      console.log(e, e.subject.data, 'fasdfasdgds');
      diagram.model.updateTargetBindings(e.subject.data);
      leaveCallBack(true);
    });
    // 监听节点拖拽到画布事件
    diagram.addDiagramListener('externalobjectsdropped', e => {
      afterNodes.current = new Map([]);
      const list = JSON.parse(diagram.model.toJson()).nodeDataArray;
      console.log(list, 'list');
      let newNum;
      let newKey;

      if (list.length > 0) {
        // eslint-disable-next-line prefer-spread
        newNum = Math.max.apply(Math, list.map(item => item.SerialNo)) + 1;
        // eslint-disable-next-line prefer-spread
        newKey = Math.max.apply(Math, list.map(item => item.key)) + 1;
      } else {
        newKey = 1;
        newNum = 1;
      }
      console.log(e);
      e.subject.each(n => {
        // 得到从Palette拖过来的节点
        console.log(n.data.key);
        let nodeData = diagram.model.findNodeDataForKey(n.data.key);
        nodeData.NodeName = `${n.data.NodeName}${newKey}`;
        nodeData.NodeAliasName = nodeData.NodeName;
        nodeData.SerialNo = newNum;
        // nodeData.key = newKey;
        nodeData.NodeId = newKey;
        nodeData.nodeDetail = JSON.stringify(nodeData);
        console.log(nodeData);
        diagram.model.updateTargetBindings(nodeData);
        diagram.model.setDataProperty(nodeData, 'key', newKey);

        currentNode.current = nodeData;
        setNodeKey(nodeData.key);
        setEditMsg(nodeData);
        setModalType('edit');
        setVisible(true);
      });
      setAddNodes([...AddNodes, newKey]);

      leaveTip();
    });
    // diagram.addDiagramListener('SelectionDeleted', e => {

    // });
  }, []);
  useEffect(() => {
    if (flowData) {
      console.log(flowData, 'msgmsgmsg');
      // 每次切换时清空删除得id数组跟新增得id数组
      setDeleteNodes([]);
      setDeleteLines([]);
      setAddNodes([]);
      setDeleteNode('');
      setDeleteLine('');
      setEditMsg({});
      let dataList = lodash.cloneDeep(flowData);
      console.log(dataList, 'dataList');

      setCurrentFlowData(dataList);
      setShowLeaveTip(false);
      setVisible(false);
    }
  }, [flowData]);
  // 存入在树形流程中选择得流程数据
  useEffect(() => {
    let nodeDataArray = [];
    let linkDataArray = [];

    // 处理老数据，让老数据可以正常展示
    limitFinshNodes.current = new Set([]);
    nodeDataArray = currentFlowData.Nodes.map((item, index) => {
      if (item.FlowTimerList.length > 0) {
        item.FlowTimerList.forEach(ele => {
          limitFinshNodes.current.add(ele.EndNode);
        });
      }
      let obj;
      obj = item;
      obj.key = item.NodeId;
      if (!obj.NodeAliasName) {
        obj.NodeAliasName = obj.NodeName;
      }
      obj.nodeDetail = JSON.stringify(obj);
      obj.CarbonCopyPeopleList = obj.CarbonCopyPeopleList.map(ele => ({
        label: ele.userName,
        value: ele.userID,
      }));
      if (obj.CCRuleList?.length > 0) {
        obj.CCRuleList.map(i => {
          if (i.UserIds?.length > 0) {
            i.UserList = i.UserIds.map(ele => ({
              label: ele.UserName,
              value: ele.UserID,
            }));
            i.UserIds = i.UserIds.map(ele => ele.UserID).toString();
          } else {
            i.UserList = [];
            i.UserIds = '';
          }
          if (i.RoleIds?.length > 0) {
            i.RoleList = i.RoleIds.map(ele => ({
              label: ele.UserName,
              value: ele.UserID,
            }));
            i.RoleIds = i.RoleIds.map(ele => ele.UserID).toString();
          } else {
            i.RoleList = [];
            i.RoleIds = '';
          }
          i.PersonList = [...i.UserList, ...i.RoleList];
        });
      }
      if (obj.points === '') {
        if (obj.NodeType === '1') {
          obj.points = `${(index * 200).toString()}" 100"`;
        } else {
          obj.points = `${(index * 200).toString()}" -22"`;
        }
      }
      return obj;
    });
    linkDataArray = currentFlowData.Lines.map(item => {
      let obj;
      obj = item;
      obj.LineKey = item.LineId;
      obj.lineDetail = JSON.stringify(obj);
      return obj;
    });

    // 保存初始数据
    setInitFlowData(
      JSON.parse(
        JSON.stringify({
          Nodes: nodeDataArray,
          Lines: linkDataArray,
        }),
      ),
    );
    diagram.model = go.Model.fromJson({
      linkFromPortIdProperty: 'fromPort', // 所需信息：
      linkToPortIdProperty: 'toPort', // 标识数据属性名称
      nodeDataArray,
      linkDataArray,
    });
    // 初次选中
    if (nodeDataArray?.length > 0) {
      currentNode.current = diagram.model.findNodeDataForKey(nodeDataArray[0].NodeId);
      setNodeKey(currentNode.current.key);
      setEditMsg(currentNode.current);
      setModalType('edit');
      setVisible(true);
    }

    // 修改复制后节点内容
    diagram.model.copyNodeDataFunction = (obj, model) => {
      let copyObj = lodash.cloneDeep(obj);
      console.log(copyObj, 'copyObj');
      copyObj.FlowTimerList.forEach(item => {
        item.key = item.ID;
        delete item.ID;
      });
      delete copyObj.ActivityId;
      delete copyObj.FlowNodeExtendId;
      return copyObj;
    };
    // 修改复制后线内容
    diagram.model.copyLinkDataFunction = (obj, model) => {
      let copyObj = lodash.cloneDeep(obj);
      delete copyObj.LineId;
      return copyObj;
    };

    diagram.model.linkKeyProperty = 'LineKey';

    diagram.model.makeUniqueLinkKeyFunction = (model, data) => {
      let i = model.linkDataArray.length * 2 + 2;
      while (model.findLinkDataForKey(i) !== null) i += 2;
      return i;
    };
  }, [currentFlowData]);
  // 删除提醒
  const showDeleteConfirm = val => {
    confirm({
      title: '确定要删除所选中的节点吗？',
      icon: <ExclamationCircleOutlined />,
      content: '',
      okText: '是',
      okType: 'danger',
      cancelText: '否',
      onOk() {
        delNode(val);
      },
      onCancel() { },
    });
  };
  // 删除节点
  const delNode = val => {
    setShowLeaveTip(true);
    // leaveCallBack(true);
    diagram.commandHandler.deleteSelection();
    // if (val.LineId) {
    //   diagram.commandHandler.deleteSelection();
    //   return;
    // }

    // DeleteFlowNode({ activityId: val.ActivityId }).then(res => {
    //   if (res.code === 0) {
    //     message.success('删除成功');
    //     diagram.commandHandler.deleteSelection();
    //   } else {
    //     message.error(res.msg);
    //   }
    // });
  };

  const animateFadeDown = e => {
    let diagrams = e.diagram;
    let animation = new go.Animation();
    animation.isViewportUnconstrained = true; // 所以图表定位规则让动画在屏幕外开始
    animation.easing = go.Animation.EaseOutExpo;
    animation.duration = 900;
    // 淡入“向下”，换句话说，从上方淡入
    animation.add(diagrams, 'position', diagrams.position.copy().offset(0, 200), diagrams.position);
    animation.add(diagrams, 'opacity', 0, 1);
    animation.start();
  };
  // 初始化拖拽面板
  const initPalette = () => {
    const defaultField = {
      aheadHandle: 1,
      NodeHandling: 1,
      RuleList: [],
      roleList: [],
      CarbonCopyPeopleList: [],
      CCRuleList: [],
      ExtendPageList: [],
      FlowNodeBackfillConfigs: [],
      FlowTimerList: [],
      TurnOnCc: 1,
      NodeAliasName: '',
      Handover: '移交选择人',
      TableName: '',
      Fields: '',
      WebPage: '',
      FeedbackName: '',
      Transferable: 0,
      EventsInformation: 0,
      IsSendMessage: 1,
      IsSave: 0,
      AutoClose: '否',
      HalfwayClose: 0,
      IsSuspend: 0,
      RollbackNode: '(上一节点)',
      Rollbackable: false,
    };
    myPaletteNode = objGo(go.Palette, 'myPaletteNode', {
      // 代替默认动画，使用自定义淡入淡出
      'animationManager.initialAnimationStyle': go.AnimationManager.None,
      InitialAnimationStarting: animateFadeDown, // 相反，使用此功能制作动画
      // nodeTemplateMap: diagram.nodeTemplateMap, // 分享 myDiagram 使用的模板
      scale: '1',
      nodeSelectionAdornmentTemplate: objGo(
        go.Adornment,
        'Auto',
        objGo(go.Shape, 'Rectangle', { fill: 'white', stroke: null }),
      ), // 去掉节点点击时的边框颜色
      model: new go.GraphLinksModel([
        // 指定调色板的内容
        {
          category: 'nodeStart',
          NodeName: '开始节点',
          NodeType: '1',
          SerialNo: 0,
          ...defaultField,
        },
        {
          category: 'nodeGeneral',
          NodeName: '普通节点',
          NodeType: '0',
          SerialNo: 0,
          ...defaultField,
        },
        {
          category: 'nodeEnd',
          NodeName: '结束节点',
          NodeType: '2',
          SerialNo: 0,
          ...defaultField,
        },
      ]),
    });
    myPaletteNode.nodeTemplate = objGo(
      go.Node,
      'Auto',
      new go.Binding('location', 'points', go.Point.parse).makeTwoWay(go.Point.stringify),
      // 节点样式配置
      objGo(
        go.Panel,
        { width: 108, height: 42 },
        objGo(
          go.Picture,
          { width: 108, height: 42 },
          new go.Binding('source', 'NodeType', v => {
            switch (v) {
              case '1':
                return require('../../../../../assets/images/workFlow/icon1.svg');
              case '2':
                return require('../../../../../assets/images/workFlow/icon3.svg');
              case '0':
                return require('../../../../../assets/images/workFlow/icon2.svg');

              default:
                return null;
            }
          }),
        ),
      ),
    );
    myPaletteGateway = objGo(go.Palette, 'myPaletteGateway', {
      // 代替默认动画，使用自定义淡入淡出
      'animationManager.initialAnimationStyle': go.AnimationManager.None,
      InitialAnimationStarting: animateFadeDown, // 相反，使用此功能制作动画
      // nodeTemplateMap: diagram.nodeTemplateMap, // 分享 myDiagram 使用的模板
      scale: '1',
      nodeSelectionAdornmentTemplate: objGo(
        go.Adornment,
        'Auto',
        objGo(go.Shape, 'Rectangle', { fill: 'white', stroke: null }),
      ), // 去掉节点点击时的边框颜色
      model: new go.GraphLinksModel([
        // 指定调色板的内容
        {
          category: 'gatewayCondition',
          NodeName: '条件网关',
          NodeType: '20',
          SerialNo: 0,
          ...defaultField,
        },
        {
          category: 'gatewayParallel',
          NodeName: '并行网关',
          NodeType: '22',
          SerialNo: 0,
          ...defaultField,
        },
        {
          category: 'gatewayJoin',
          NodeName: '汇合网关',
          NodeType: '21',
          SerialNo: 0,
          ...defaultField,
        },
      ]),
    });
    myPaletteGateway.nodeTemplate = objGo(
      go.Node,
      'Auto',
      new go.Binding('location', 'points', go.Point.parse).makeTwoWay(go.Point.stringify),
      // 节点样式配置
      objGo(
        go.Panel,
        { width: 108, height: 42 },
        objGo(
          go.Picture,
          { width: 108, height: 42 },
          new go.Binding('source', 'NodeType', v => {
            switch (v) {
              case '20':
                return require('../../../../../assets/images/workFlow/gateWayicon1.svg');
              case '21':
                return require('../../../../../assets/images/workFlow/gateWayicon3.svg');
              case '22':
                return require('../../../../../assets/images/workFlow/gateWayicon2.svg');
              default:
                return null;
            }
          }),
        ),
      ),
    );
    myPaletteSubprocess = objGo(go.Palette, 'myPaletteSubprocess', {
      // 代替默认动画，使用自定义淡入淡出
      'animationManager.initialAnimationStyle': go.AnimationManager.None,
      InitialAnimationStarting: animateFadeDown, // 相反，使用此功能制作动画
      // nodeTemplateMap: diagram.nodeTemplateMap, // 分享 myDiagram 使用的模板
      scale: '1',
      nodeSelectionAdornmentTemplate: objGo(
        go.Adornment,
        'Auto',
        objGo(go.Shape, 'Rectangle', { fill: 'white', stroke: null }),
      ), // 去掉节点点击时的边框颜色
      model: new go.GraphLinksModel([
        // 指定调色板的内容
        {
          category: 'gatewayCondition',
          NodeName: '子流程',
          NodeType: '30',
          SerialNo: 0,
          ...defaultField,
        },
      ]),
    });
    myPaletteSubprocess.nodeTemplate = objGo(
      go.Node,
      'Auto',
      new go.Binding('location', 'points', go.Point.parse).makeTwoWay(go.Point.stringify),
      // 节点样式配置
      objGo(
        go.Panel,
        { width: 108, height: 42 },
        objGo(
          go.Picture,
          { width: 108, height: 42 },
          new go.Binding('source', 'NodeType', v => {
            switch (v) {
              case '30':
                return require('../../../../../assets/images/workFlow/subprocessicon.svg');

              default:
                return null;
            }
          }),
        ),
      ),
    );
  };
  // 流程图初始化
  const init = () => {
    diagram = objGo(go.Diagram, 'myDiagramDiv', {
      'undoManager.isEnabled': true,
      allowDragOut: false,
      'dragSelectingTool.isEnabled': false, // 禁止多选
      // 'grid.visible': true,
      scrollMode: go.Diagram.InfiniteScroll, // 无限滚动
      allowCopy: true, // 禁止复制
      allowDrop: true,
      // nodeSelectionAdornmentTemplate: objGo(
      //   go.Adornment,
      //   'Auto',
      //   objGo(go.Shape, 'Rectangle', { fill: 'white', stroke: null }),
      // ), // 去掉节点点击时的边框颜色
      scale: '0.8',
    });
    diagram.grid.gridCellSize = new go.Size(10, 10);
    diagram.toolManager.draggingTool.isGridSnapEnabled = true;

    // 节点配置
    diagram.nodeTemplate = objGo(
      go.Node,
      'Auto',
      new go.Binding('location', 'points', go.Point.parse).makeTwoWay(go.Point.stringify),
      // 节点样式配置
      objGo(
        go.Panel,
        nodeBoxStyle('width'),
        nodeBoxStyle('height'),
        objGo(
          go.Picture,
          new go.Binding('source', 'NodeType', v => {
            switch (v) {
              case '1':
                return nodeStart;
              case '2':
                return nodeEnd;
              case '0':
                return nodeGeneral;
              // case '4':
              //   return cc;
              case '20':
                return gatewayCondition;
              case '21':
                return gatewayJoin;
              case '22':
                return gatewayParallel;
              case '30':
                return require('../../../../../assets/images/workFlow/nodesubprocess.svg');
              default:
                return null;
            }
          }),
          nodeBoxStyle('width'),
          nodeBoxStyle('height'),
        ),
        objGo(
          go.Panel,
          'Horizontal',
          nodeBoxStyle('height'),
          { alignment: go.Spot.Center },
          objGo(
            go.Panel,
            'Vertical', // 节点文案

            nodeBoxStyle('width'),
            objGo(
              go.TextBlock,
              {
                maxSize: new go.Size(120, NaN),
                maxLines: 1,
                alignment: go.Spot.Center,
                margin: new go.Margin(0, 15, 0, 15),
                overflow: go.TextBlock.OverflowEllipsis,
                font: 'normal 12pt Microsoft YaHei',
              },
              new go.Binding('visible', 'NodeType', v => {
                if (v.NodeType === '20' || v.NodeType === '21' || v.NodeType === '22') {
                  return false;
                }
                return true;
              }),
              new go.Binding('text', 'NodeAliasName'),
              nodeBoxStyle('stroke', 'nodeStyle'),
            ),
            objGo(
              go.TextBlock,

              {
                alignment: go.Spot.Center,
                maxLines: 2,
                overflow: go.TextBlock.OverflowEllipsis,
                font: 'normal 12pt Microsoft YaHei',
              },
              new go.Binding('spacingAbove', 'roleList', v => (v?.length > 0 ? 5 : 0)),
              new go.Binding('height', 'roleList', v => (v?.length > 0 ? 30 : 0)),
              new go.Binding('margin', 'roleList', v =>
                v?.length > 0 ? new go.Margin(10, 10, 0, 10) : 0,
              ),
              new go.Binding('text', 'nodeDetail', v => {
                const obj = JSON.parse(v);

                if (obj.NodeType === '20' || obj.NodeType === '21' || obj.NodeType === '22') {
                  return '';
                }
                if (obj.roleList?.length === 0) {
                  return '';
                }
                return obj.roleList.map(item => item.roleName).join(',');
              }),
              nodeBoxStyle('stroke', 'roleStyle'),
            ),
          ),
        ),
      ),

      // 我们的小命名端口，每侧一个：
      makePort('T', go.Spot.Top),
      makePort('L', go.Spot.Left),
      makePort('R', go.Spot.Right),
      makePort('B', go.Spot.Bottom),
      {
        // 节点之间线得连接
        linkValidation(fromnode, fromport, tonode, toport, thisLink) {
          // 并行网关不让连接汇合网关
          if (fromnode.data.NodeType === '22' && tonode.data.NodeType === '21') {
            return false;
          }
          // 条件网关不让连接条件网关
          if (fromnode.data.NodeType === '20' && tonode.data.NodeType === '20') {
            return false;
          }
          // 汇合网关不让连条件网关
          if (fromnode.data.NodeType === '21' && tonode.data.NodeType === '20') {
            return false;
          }
          return true;
        },
        // 处理鼠标进入/离开事件以显示/隐藏端口
        mouseEnter(e, node) {
          showSmallPorts(node, true);
        },
        mouseLeave(e, node) {
          showSmallPorts(node, false);
        },
        click(e, node) {
          handlerDC(e, node);
        },
        // 处理双击
        doubleClick(e, node) {
          // 双击事件
          // handlerDC(e, node); // 双击执行的方法
        },
        selectionChanged: node => {
          // console.log(node.data, 'nodenodenode');
        },
        toolTip: objGo(
          'ToolTip',
          objGo(
            go.TextBlock,
            { margin: 4 },
            new go.Binding('text', 'nodeDetail', v => {
              const obj = JSON.parse(v);
              return `节点名称:${obj.NodeName}\n${obj.roleList.length > 0 ? '承办:' : ''
                }${obj.roleList.map(item => item.roleName).join(',')}`;
            }),
          ),
        ),
      },
    );
    // 链接设置
    diagram.linkTemplate = objGo(
      go.Link,
      {
        routing: go.Link.Orthogonal,
        curve: go.Link.JumpOver,
        corner: 5,
        toShortLength: 4,
        selectionAdornmentTemplate: objGo(
          go.Adornment,
          objGo(go.Shape, { isPanelMain: true, stroke: '#faad14', strokeWidth: 2 }), // 修改线颜色和大小
          objGo(go.Shape, { toArrow: 'Standard', fill: '#faad14', stroke: '#faad14' }), // 修改线箭头的颜色和大小
        ),
      },
      new go.Binding('points').makeTwoWay(),
      objGo(
        go.Shape, // 链接路径形状
        {
          isPanelMain: true,
          strokeWidth: 2,
        },

        new go.Binding('stroke', 'from', v => lineStyle(v, 'stroke')),
        new go.Binding('strokeDashArray', 'from', v => lineStyle(v, 'strokeDashArray')),
      ),
      objGo(
        go.Shape, // 箭头
        { toArrow: 'Standard' },
        new go.Binding('stroke', 'from', v => lineStyle(v, 'stroke')),
        new go.Binding('fill', 'from', v => lineStyle(v, 'stroke')),
      ),
      objGo(
        go.Panel,
        'Auto',
        objGo(
          go.Shape, // 标签背景，在边缘变得透明
          // { fill: 'transparent' },
          new go.Binding('fill', 'lineDetail', v => lineTextStyle(v)),
          new go.Binding('stroke', 'lineDetail', v => lineTextStyle(v)),
        ),
        objGo(
          go.TextBlock,
          {
            textAlign: 'center',
            font: '10pt helvetica, arial, Microsoft YaHei',
            stroke: '#555555',
            margin: 4,
          },
          new go.Binding('text', 'lineDetail', v => lineText(v)),
        ),
      ),

      // {
      //   // 处理双击
      //   doubleClick(e, node) {
      //     addLineMsg(e, node);
      //   },
      // },
    );
    // 初始化流程的节点数组
    diagram.model = objGo(go.GraphLinksModel, {
      linkFromPortIdProperty: 'fromPort', // 所需信息：
      linkToPortIdProperty: 'toPort', // 标识数据属性名称
      nodeDataArray: currentFlowData.Nodes,
      linkDataArray: currentFlowData.Lines,
    });
  };

  // 线的样式
  const lineStyle = (v, styleName) => {
    const linemsg = diagram.model.findNodeDataForKey(v);
    switch (styleName) {
      case 'strokeDashArray':
        if (linemsg.NodeType === '20') {
          return [6, 3];
        }
        return null;
      case 'stroke':
        return '#1685FF';
      default:
        return null;
    }
  };
  // 线上文案样式
  const lineTextStyle = v => {
    let obj = JSON.parse(v);

    let nodeData = diagram.model.findNodeDataForKey(obj.from);
    if (nodeData.NodeType === '20' || nodeData.NodeType === '21') {
      // if(nodeData.)
      if (nodeData.RuleList.some(ele => ele.NextNodeId === obj.to)) {
        return '#EFF8FA';
      }
      return 'transparent';
    }
    return 'transparent';
  };
  // 线上的文案
  const lineText = v => {
    let obj = JSON.parse(v);
    let nodeData = diagram.model.findNodeDataForKey(obj.from);
    if (nodeData.NodeType === '20' || nodeData.NodeType === '21') {
      return nodeData.RuleList.find(ele => ele.NextNodeId === obj.to).RuleName;
    }
    return '';
  };
  // 是否显示端口
  const showSmallPorts = (node, show) => {
    node.ports.each(port => {
      if (port.portId !== '') {
        // 不要更改默认端口，这是大形状
        port.fill = show ? 'rgba(5,135,224,.3)' : null;
      }
    });
  };
  // 创建节点端口
  const makePort = (name, spot) =>
    // 端口基本上只是一个小的透明 方块
    objGo(
      go.Shape,
      'Circle',
      {
        fill: null, // 默认情况下不可见； 由 showSmallPorts 设置为半透明灰色，定义如下
        stroke: null,
        desiredSize: new go.Size(8, 8),
        alignment: spot, // 对齐主要形状上的端口
        alignmentFocus: spot, // 就在形状里面
        portId: name, // 将此对象声明为“端口”
        fromSpot: spot,
        toSpot: spot, // 声明链接可以在此端口连接的位置
        cursor: 'pointer', // 显示不同的光标以指示潜在的链接点
      },
      new go.Binding('fromLinkable', 'NodeType', v => v !== '2'), // 是否允许用户绘制的链接到这里
      new go.Binding('toLinkable', 'NodeType', v => v !== '1'), // 声明用户是否可以从这里绘制链接
    );
  //  节点盒子样式
  const nodeBoxStyle = (atr, classname) => {
    switch (atr) {
      case 'width':
        return new go.Binding('width', 'NodeType', v => {
          switch (v) {
            case '1':
              return 140;
            case '2':
              return 140;
            case '0':
              return 220;
            case '4':
              return 220;
            case '20':
              return 60;
            case '21':
              return 60;
            case '22':
              return 60;
            case '30':
              return 220;
            default:
              return null;
          }
        });
      case 'height':
        return new go.Binding('height', 'NodeType', v => {
          switch (v) {
            case '1':
              return 140;
            case '2':
              return 140;
            case '0':
              return 120;
            case '4':
              return 120;
            case '20':
              return 60;
            case '21':
              return 60;
            case '22':
              return 60;
            case '30':
              return 120;
            default:
              return null;
          }
        });
      case 'stroke':
        return new go.Binding('stroke', 'NodeType', v => {
          switch (v) {
            case '1':
              return classname === 'roleStyle' ? '#BCBCBC' : '#1685FF';
            case '2':
              return classname === 'roleStyle' ? '#BCBCBC' : '#51C21A';
            case '0':
              return classname === 'roleStyle' ? '#BCBCBC' : '#1685FF';
            case '30':
              return classname === 'roleStyle' ? '#BCBCBC' : '#9850F6';
            default:
              return null;
          }
        });
      default:
        return null;
    }
  };
  const findAfterNode = startNode => {
    // let nodeList = new Map([]);
    startNode.findNodesOutOf().each(node => {
      if (!afterNodes.current.has(node.data.NodeName)) {
        if (['1', '0', '2'].includes(node.data.NodeType)) {
          afterNodes.current.set(node.data.NodeName, node.data.TableName);
        }
        findAfterNode(node);
      }
    });
  };
  // 双击节点
  const handlerDC = (e, node) => {
    currentNode.current = node.data;

    // 找到节点后得除去网关跟子流程的所有节点
    afterNodes.current = new Map([]);
    findAfterNode(node);
    console.log(Object.fromEntries(afterNodes.current));
    setModalType('edit');
    setVisible(true);
    setNodeKey(node.part.data.key);
    setEditMsg(node.part.data);
  };
  // 双击线
  const addLineMsg = (e, node) => {
    setLineKey(node.part.data.LineKey);
    setLineMsg(node.part.data);
    setLineVisible(true);
  };

  const copyNode = e => {
    diagram.commandHandler.canSelectAll();
  };
  // 节点配置回调
  // const nodeCallBack = obj => {
  //   let nameIsRepeat;
  //   let { nodes } = diagram;
  //   let keyArr = [];
  //   // 遍历输出节点对象
  //   nodes.each(node => {
  //     keyArr = [...keyArr, Number(node.data.key)];
  //     if (obj.NodeName === node.data.NodeName) {
  //       nameIsRepeat = true;
  //       if (modalType === 'edit' && obj.NodeName === editMsg.NodeName) {
  //         nameIsRepeat = false;
  //       }
  //     }
  //   });
  //   if (nameIsRepeat) {
  //     notification.error({
  //       message: '提示',
  //       duration: 3,
  //       description: '节点名称不能重复',
  //     });
  //     return;
  //   }
  //   // 编辑节点
  //   let nodeData = diagram.model.findNodeDataForKey(nodeKey);
  //   const {
  //     NodeName,
  //     NodeType,
  //     roleList,
  //     SerialNo,
  //     aheadHandle,
  //     NodeHandling,
  //     nodeDetail,
  //     RuleList,
  //     CarbonCopyPeopleList,
  //     SubFlowInfo,
  //   } = obj;
  //   nodeData.NodeName = NodeName;
  //   nodeData.NodeType = NodeType;
  //   nodeData.NodeId = nodeKey;
  //   nodeData.roleList = roleList;
  //   nodeData.SerialNo = SerialNo;
  //   nodeData.aheadHandle = aheadHandle;
  //   nodeData.NodeHandling = NodeHandling;
  //   nodeData.nodeDetail = nodeDetail;
  //   nodeData.RuleList = RuleList;
  //   nodeData.CarbonCopyPeopleList = CarbonCopyPeopleList;
  //   nodeData.SubFlowInfo = SubFlowInfo;
  //   diagram.model.updateTargetBindings(nodeData);

  //   // 给线上添加文字
  //   let diagramObj = JSON.parse(diagram.model.toJson());
  //   console.log(diagramObj.linkDataArray, 'diagramObj.linkDataArray');
  //   diagramObj.linkDataArray.forEach(item => {
  //     let node = diagram.model.findLinkDataForKey(item.LineKey);
  //     node.text = item.RuleName;
  //     diagram.model.updateTargetBindings(node);
  //   });
  //   // 关闭时进行数据比对看数据是否改变
  //   leaveTip();
  //   // setVisible(false);
  // };
  const nodeCallBack = () => {
    FlowNodeSave({
      flowID,
      ...currentNode.current,
      CarbonCopyPeopleList: currentNode.current.CarbonCopyPeopleList.map(item =>
        Number(item.value),
      ),
    }).then(res => {
      if (res.code === 0) {
        diagram.model.setDataProperty(currentNode.current, 'FlowTimerList', res.data.FlowTimerList);
        diagram.model.setDataProperty(currentNode.current, 'ActivityId', res.data.ActivityId);
        diagram.model.setDataProperty(
          currentNode.current,
          'FlowNodeExtendId',
          res.data.FlowNodeExtendId,
        );
        message.success('保存成功');
      } else {
        message.error(res.msg);
      }
    });
  };
  // 关闭时进行数据比对看数据是否改变
  const leaveTip = () => {
    let diagramObj = JSON.parse(diagram.model.toJson());
    let stageJson = {
      Nodes: diagramObj.nodeDataArray,
      Lines: diagramObj.linkDataArray,
    };
    if (JSON.stringify(stageJson.Nodes) === JSON.stringify(initFlowData.Nodes)) {
      setShowLeaveTip(false);
      leaveCallBack(false);
    } else {
      leaveCallBack(true);
      setShowLeaveTip(true);
    }
  };
  // 线配置回调函数
  const lineCallBack = obj => {
    let node = diagram.model.findLinkDataForKey(LineKey);
    node.text = obj.text;
    diagram.model.updateTargetBindings(node);

    // 关闭时进行数据比对看数据是否改变
    leaveTip();
    setLineVisible(false);
  };
  // 获取保存后的流程数据
  const getFlowData = () => {
    GetFlowNode({ flowID }).then(res => {
      if (res.code === 0) {
        // 保存后离开不用提醒要修改数据了
        setShowLeaveTip(false);
        leaveCallBack(false);

        setCurrentFlowData(JSON.parse(JSON.stringify(res.data)));
      } else {
        notification.error({
          title: '提示',
          duration: 3,
          description: res.msg,
        });
      }
    });
  };
  const isRepeat = (arr, key) => {
    let obj = {};
    for (let i = 0; i < arr.length; i++) {
      if (obj[arr[i][key]]) {
        return false;
      }
      obj[arr[i][key]] = arr[i];
    }
    return obj;
  };
  // 节点数据改边
  const nodeChage = (key, value) => {
    let obj = JSON.parse(JSON.stringify(currentNode.current));
    obj[key] = value;
    const nodeDetail = JSON.stringify(obj);

    diagram.model.setDataProperty(currentNode.current, key, value);
    if (key === 'roleList') {
      diagram.model.setDataProperty(currentNode.current, 'nodeDetail', nodeDetail);
    }
    if (key === 'FlowTimerList') {
      const list = value.map(item => item.EndNode);
      limitFinshNodes.current = new Set(list);
      setFlag(flag + 1);
      // limitFinshNodes;
    }
    if (key === 'TableName') {
      setFlag(flag + 1);
    }

    diagram.rebuildParts();
    leaveCallBack(true);
  };
  // 保存流程
  const saveFlow = () => {
    let diagramObj = JSON.parse(diagram.model.toJson());
    // let list = isRepeat(diagramObj.nodeDataArray, 'SerialNo');

    // if (!list) {
    //   notification.error({
    //     message: '提示',
    //     duration: 3,
    //     description: '请检查序号是否重复',
    //   });
    //   return;
    // }
    let list = new Set([]);
    console.log(list, '11111');
    diagramObj.nodeDataArray.forEach(item => {
      if ((item.NodeType === '20' || item.NodeType === '21') && item.RuleList) {
        item.RuleList.forEach(ele => {
          if (!ele.RuleName) {
            list.add(item.NodeName);

            return;
          }
          if (!ele.NextNodeId && ele.NextNodeId !== 0) {
            list.add(item.NodeName);

            return;
          }
          if (!ele.RuleContent) {
            list.add(item.NodeName);
          }
        });
      }
      const newListLength = new Set(item.RuleList.map(ele => ele.NextNodeId)).size;
      if (item.RuleList.length > newListLength) {
        list.add(item.NodeName);
        return;
      }
      item.CarbonCopyPeopleList = item.CarbonCopyPeopleList.map(ele => Number(ele.value));
    });
    console.log(list, '222');
    if ([...list].length > 0) {
      list.forEach(item => {
        message.error(`请检查${item}规则配置`);
      });
      return;
    }
    setButtonLoading(true);
    SaveNodeChange({
      FlowId: flowID,
      // DeleteNodes,
      DeleteLines,
      Lines: diagramObj.linkDataArray,
      Nodes: diagramObj.nodeDataArray,
    })
      .then(res => {
        setButtonLoading(false);
        if (res.code === 0) {
          setDeleteNodes([]);
          setDeleteLines([]);
          setAddNodes([]);
          setDeleteNode('');
          setDeleteLine('');
          getFlowData();
          notification.success({
            message: '提示',
            duration: 3,
            description: '保存成功',
          });
        } else {
          notification.error({
            message: '提示',
            duration: 8,
            description: res.msg,
          });
        }
      })
      .catch(() => {
        setButtonLoading(false);
        notification.error({
          message: '提示',
          duration: 3,
          description: '网络异常请稍后重试',
        });
      });
  };

  return (
    <>
      <Prompt message="编辑的内容还未保存，确定要离开该页面吗?" when={showLeaveTip} />
      <div className={styles.control}>
        <div className={styles.nodeList}>
          <div id="myPaletteNode" className={styles.myPaletteDiv} />
          {/* <div className={styles.lineBox} /> */}
          <div id="myPaletteGateway" className={styles.myPaletteDiv} />
          <div id="myPaletteSubprocess" className={styles.myPaletteSubprocess} />
        </div>
        <div className={styles.buttonList}>
          {/* <Button
            type="link"
            onClick={() => {
              window.open(
                'https://www.yuque.com/docs/share/da224db9-b8d1-49d2-838f-a23fcd15f0da?#%20%E3%80%8A%E6%B5%81%E7%A8%8B%E8%AE%BE%E8%AE%A1%E3%80%8B',
              );
            }}
          >
            说明文档
          </Button> */}
          {/* <Button type="link" onClick={() => copyNode()}>
            复制
          </Button> */}
          <Button type="primary" onClick={() => saveFlow()} loading={buttonLoading}>
            发布
          </Button>
        </div>
      </div>
      <div className={styles.chartBox}>
        <div id="myOverviewDiv" className={styles.myOverviewDiv} />
        <div className={styles.flowName}>{flowData.flowName}</div>
        <Spin spinning={chartLoading}>
          <div
            id="myDiagramDiv"
            className={styles.myDiagramDiv}
            style={{ backgroundColor: '#EFF8FA' }}
          />
        </Spin>
        <NodeModal
          flowID={flowID}
          visible={visible}
          editMsg={editMsg}
          modalType={modalType}
          nodeChage={nodeChage}
          currentNode={currentNode.current}
          limitFinshNodes={[...limitFinshNodes.current]}
          afterNodes={Object.fromEntries(afterNodes.current)}
          handleCancel={() => setVisible(false)}
          onSubumit={obj => nodeCallBack(obj)}
          flowData={diagram ? JSON.parse(diagram.model.toJson()) : {}}
        />
      </div>

      <LineModal
        visible={lineVisible}
        lineMsg={lineMsg}
        handleCancel={() => setLineVisible(false)}
        onSubumit={obj => lineCallBack(obj)}
      />
    </>
  );
};

export default FlowChart;
