/* eslint-disable global-require */
import React, { useState, useEffect, useRef } from 'react';
import { useHistory, Prompt } from 'react-router-dom';
import { Button, Modal, notification, Spin, Empty, Tooltip, message, TreeSelect } from 'antd';
import lodash from 'lodash';
import {
  SaveNodeChange,
  GetFlowNode,
  FlowNodeSave,
  DeleteFlowNode,
  DeleteFlowNodes,
  SaveWorkFlowImage,
  CheckDoingFlowNodes,
  CloseDoingFlowNodes,
} from '@/services/workflow/workflow';
import { compress } from '@/utils/utils';
import { ExclamationCircleOutlined, TrophyOutlined } from '@ant-design/icons';
import * as go from 'gojs';
import styles from './FlowBoard.less';
// 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;
const { TreeNode } = TreeSelect;
let diagram = null;
let myPaletteNode = null;
let myPaletteGateway = null;
let myPaletteSubprocess = null;
let myOverview = null;
const FlowChart = props => {
  const history = useHistory();

  const {
    flowData,
    flowID,
    chartLoading,
    msg,
    treeVisible,
    activeKey,
    flowTree,
    scrollTop,
  } = 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 [selectValue, setSelectValue] = useState();
  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(res.msg);
    //       message.error({
    //         content: <div style={{ whiteSpace: 'pre-line', textAlign: 'justify' }}>{res.msg}</div>,
    //       });
    //     }
    //   });
    //   console.log(delNodes, delLinks, 'fffff');
    // });
    // 监听节点或线的删除前事件
    diagram.commandHandler.canDeleteSelection = () => {
      let delNodes = new Set();
      let delNodeIds = new Set();
      let delLinks = new Set();
      diagram.selection.toArray().forEach(item => {
        if (item.data.ActivityId) {
          delNodes.add(item.data.ActivityId);
          delNodeIds.add(item.data.NodeId);
          item.findLinksConnected().each(link => {
            if (link.data.LineId) {
              delLinks.add(link.data.LineId);
            }
          });
        }
        if (item.data.LineId) {
          delLinks.add(item.data.LineId);
        }
      });
      if (delNodes.size === 0) {
        delNode([...delNodeIds], [...delNodes], [...delLinks]);
      } else {
        CheckDoingFlowNodes({ activityIds: [...delNodes] }).then(res => {
          if (res.code === 0) {
            if (res.data > 0) {
              showCloseList([...delNodeIds], [...delNodes], [...delLinks], res.data);
            } else {
              showDeleteConfirm([...delNodeIds], [...delNodes], [...delLinks]);
            }
          } else {
            message.error(res.msg);
          }
        });
      }

      return false;
    };
    // 监听线,连接线的时候加上text属性
    diagram.addDiagramListener('LinkDrawn', e => {
      // e.subject.data.text = '';
      e.subject.data.lineDetail = JSON.stringify(e.subject.data);
      diagram.model.updateTargetBindings(e.subject.data);
      // leaveCallBack(true);
    });
    // 监听节点拖拽到画布事件
    diagram.addDiagramListener('externalobjectsdropped', e => {
      afterNodes.current = new Map([]);
      const list = JSON.parse(diagram.model.toJson()).nodeDataArray;
      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.toString(),
            }));
            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[nodeDataArray.length - 1].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 showCloseList = (delNodeIds, delNodes, delLinks, listMsg) => {
    confirm({
      title: '确定要删除所选节点吗？',
      icon: <ExclamationCircleOutlined />,
      content: <div>当前节点有{listMsg}条在办工单，确定删除会自动归档在办工单。</div>,
      okText: '是',
      okType: 'primary',
      cancelText: '否',

      onOk() {
        CloseDoingFlowNodes({ activityIds: [...delNodes] }).then(res => {
          if (res.code === 0) {
            delNode(delNodeIds, delNodes, delLinks);
          } else {
            message.error(res.msg);
          }
        });
      },
      onCancel() {},
    });
  };
  // 删除提醒
  const showDeleteConfirm = (delNodeIds, delNodes, delLinks) => {
    confirm({
      title: '确定要删除所选中的节点吗？',
      icon: <ExclamationCircleOutlined />,
      content: '',
      okText: '是',
      okType: 'primary',
      cancelText: '否',
      onOk() {
        delNode(delNodeIds, delNodes, delLinks);
      },
      onCancel() {},
    });
  };
  // 删除节点
  const delNode = (delNodeIds, delNodes, delLinks) => {
    console.log(delNodeIds, delNodes, delLinks);
    setShowLeaveTip(true);
    if (delNodes.length === 0) {
      console.log(DeleteLines, [...DeleteLines, ...delLinks], '[...DeleteLines, ...delLinks]');
      setDeleteLine(delLinks);
      diagram.commandHandler.deleteSelection();
      return;
    }
    DeleteFlowNodes({ ActivityIds: delNodes, LineIds: delLinks }).then(res => {
      if (res.code === 0) {
        diagram.commandHandler.deleteSelection();

        setDeleteNode(delNodeIds);
        setDeleteLine(delLinks);
        message.success('删除成功');
      } else {
        // message.error(res.msg);
        message.error({
          content: <div style={{ whiteSpace: 'pre-line', textAlign: 'justify' }}>{res.msg}</div>,
        });
      }
    });
  };

  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: '',
      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,
          Handover: '移交选择人',
          ...defaultField,
        },
        {
          category: 'nodeGeneral',
          NodeName: '普通节点',
          NodeType: '0',
          SerialNo: 0,
          Handover: '移交选择人',
          ...defaultField,
        },
        {
          category: 'nodeEnd',
          NodeName: '结束节点',
          NodeType: '2',
          SerialNo: 0,
          Handover: '自处理',
          ...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();
    console.log(
      diagram.makeImageData({
        background: 'rgb(239, 248, 250)',
        maxSize: new go.Size(1260, 500),
      }),
      'fasdfsad',
    );
  };
  const nodeCallBack = () => {
    compress(
      diagram.makeImageData({
        background: 'rgb(239, 248, 250)',
        // maxSize: new go.Size(1260, 500), // 固定区域
        scale: 1, // 有效区域
      }),
      1.2, // 压缩比例
      base64 => {
        SaveWorkFlowImage({
          flowName: flowData.flowName,
          base64Data: base64,
        }).then(response => {
          if (response.code === 0) {
            let flowNodeBackfillConfigs = currentNode.current.FlowNodeBackfillConfigs;
            currentNode.current.FlowNodeBackfillConfigs = jsonData(flowNodeBackfillConfigs);
            FlowNodeSave({
              PreviewImage: response.data,
              CreateUser: sessionStorage.getItem('userName'),
              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 isJSON = str => {
    if (str && str.indexOf('{') !== -1) {
      return true;
    }
    return false;
  };

  const jsonData = val => {
    let listArr = [];
    val.map((item, index) => {
      console.log(item);
      if (!item.Config) {
        console.log(item);
        let arr = [];
        arr.push({
          mapServer: item.schemeName,
          tableName: item[0].nodeName,
          filed: item[0].nodeValue,
        });
        if (item.users) {
          item.users.map(i => {
            arr.push({
              mapServer: item.schemeName,
              tableName: i.nodeName,
              filed: i.nodeValue,
            });
          });
        }
        let obj = {};
        obj.type = 'GIS';
        if (item.tableType === 'mapping') {
          obj.mapping = [
            {
              fromData: {
                tableName: item.TableName,
                filed: item.Fields,
                filedShape: item.tableShape,
              },
              toData: arr,
            },
          ];
        } else {
          obj.relationFormMapping = [
            {
              fromData: {
                tableName: item.TableName,
                filed: item.Fields,
                filedShape: item.tableShape,
              },
              toData: arr,
            },
          ];
        }
        let json = JSON.stringify(obj);
        let newObj = { Config: json, BackfillType: 'GIS', RuleName: item.RuleName };
        listArr.push(newObj);
      } else {
        listArr.push(item);
      }
    });
    return listArr;
  };
  // 关闭时进行数据比对看数据是否改变
  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 {
        message.error(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) => {
    setShowLeaveTip(true);
    let obj = JSON.parse(JSON.stringify(currentNode.current));
    if (key === 'saveBtnAliasName') {
      let data = obj.BtnAliasNameConfig === '' ? {} : JSON.parse(obj.BtnAliasNameConfig);
      data.saveBtnAliasName = value;
      obj.BtnAliasNameConfig = JSON.stringify(data);
      diagram.model.setDataProperty(
        currentNode.current,
        'BtnAliasNameConfig',
        obj.BtnAliasNameConfig,
      );
    } else if (key === 'HalfwayCloseBtnAliasName') {
      let data = obj.BtnAliasNameConfig === '' ? {} : JSON.parse(obj.BtnAliasNameConfig);
      data.HalfwayCloseBtnAliasName = value;
      obj.BtnAliasNameConfig = JSON.stringify(data);
      diagram.model.setDataProperty(
        currentNode.current,
        'BtnAliasNameConfig',
        obj.BtnAliasNameConfig,
      );
      // currentNode.current = obj;
    } else if (key === 'TransferableBtnAliasName') {
      let data = obj.BtnAliasNameConfig === '' ? {} : JSON.parse(obj.BtnAliasNameConfig);
      data.TransferableBtnAliasName = value;
      obj.BtnAliasNameConfig = JSON.stringify(data);
      diagram.model.setDataProperty(
        currentNode.current,
        'BtnAliasNameConfig',
        obj.BtnAliasNameConfig,
      );
      // currentNode.current = obj;
    } else if (key === 'RollbackBtnAliasName') {
      let data = obj.BtnAliasNameConfig === '' ? {} : JSON.parse(obj.BtnAliasNameConfig);
      data.RollbackBtnAliasName = value;
      obj.BtnAliasNameConfig = JSON.stringify(data);
      diagram.model.setDataProperty(
        currentNode.current,
        'BtnAliasNameConfig',
        obj.BtnAliasNameConfig,
      );
      // currentNode.current = obj;
    } else {
      diagram.model.setDataProperty(currentNode.current, key, value);
    }
    obj[key] = value;
    const nodeDetail = JSON.stringify(obj);

    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);
    }
    if (key === 'FlowNodeBackfillConfigs') {
      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([]);
    let errorList = new Set();
    diagramObj.nodeDataArray.forEach(item => {
      if (item.NodeType !== '20' && item.NodeType !== '21' && item.RuleList) {
        item.RuleList = [];
      }
      if (item.NodeType === '1' || item.NodeType === '1' || item.NodeType === '1') {
        if (!item.TableName || !item.Fields) {
          errorList.add(item.NodeName);
        }
      }
      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));
    });
    if ([...errorList].length > 0) {
      errorList.forEach(item => {
        message.error(`请检查${item}节点存在未配置项`);
      });
      return;
    }
    if ([...list].length > 0) {
      list.forEach(item => {
        message.error(`请检查${item}规则配置`);
      });
      return;
    }
    setButtonLoading(true);
    compress(
      diagram.makeImageData({
        background: 'rgb(239, 248, 250)',
        // maxSize: new go.Size(1260, 500), // 固定区域
        scale: 1, // 有效区域
      }),
      1.2, // 压缩比例
      base64 => {
        SaveWorkFlowImage({
          flowName: flowData.flowName,
          base64Data: base64,
        }).then(val => {
          if (val.code === 0) {
            diagramObj.nodeDataArray.map(i => {
              i.FlowNodeBackfillConfigs = jsonData(i.FlowNodeBackfillConfigs);
            });
            SaveNodeChange({
              FlowId: flowID,
              // DeleteNodes,
              CreateUser: sessionStorage.getItem('userName'),
              PreviewImage: val.data,
              DeleteLines,
              Lines: diagramObj.linkDataArray,
              Nodes: diagramObj.nodeDataArray,
            })
              .then(res => {
                setButtonLoading(false);
                if (res.code === 0) {
                  setDeleteNodes([]);
                  setDeleteLines([]);
                  setAddNodes([]);
                  setDeleteNode([]);
                  setDeleteLine([]);
                  getFlowData();
                  message.success('保存成功');
                } else {
                  message.error(res.msg);
                }
              })
              .catch(() => {
                setButtonLoading(false);
                message.error('网络异常请稍后重试');
              });
          }
        });
      },
    );
  };

  const treeChange = newValue => {
    setSelectValue(newValue);
  };
  const mapAppTree = org => {
    const haveChildren = Array.isArray(org.children) && org.children.length > 0;
    let value;
    let text;
    if (org.name) {
      value = org.name;
      text = org.name;
    }
    if (org.Code) {
      value = org.Code;
      text = org.FlowName;
    }

    return (
      <TreeNode value={value} title={text} key={value} disabled={org.name}>
        {haveChildren ? org.children.map(item => mapAppTree(item)) : null}
      </TreeNode>
    );
  };
  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="link" onClick={() => copyNode()}>
            <TreeSelect
              value={selectValue}
              showSearch
              style={{ width: '200px' }}
              treeNodeFilterProp="title"
              dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
              placeholder="请选择流程"
              treeDefaultExpandAll
              onChange={treeChange}
              treeIcon
            >
              {flowTree ? (
                flowTree.map(item => mapAppTree(item))
              ) : (
                <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
              )}
            </TreeSelect>
          </Button> */}
          <Button
            onClick={() =>
              history.push({
                pathname: '/biz/workflow/center',
                state: {
                  activeKey,
                  scrollTop,
                },
              })
            }
          >
            返回
          </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;
