import { Graph, Node, EventArgs, Cell } from "@antv/x6";
import {
  BatchAddFlowchartElement,
  BatchEditFlowchartElement,
  BatchDeleteFlowchartElement,
} from "@/api/systemDesigner";
import { getBasicData } from "@/utils/diffrence";
export const handleGraphEvent = (graph: Graph) => {
  // 边开始拖拽点
  const sourceArrowhead = {
    name: "source-arrowhead",
    args: {
      attrs: {
        d: "M -5,-5 5,-5 5,5 -5,5 Z",
        fill: "#fff",
        stroke: "#239edd",
        "stroke-width": 1,
      },
    },
  };
  // 边结束拖拽点
  const targetArrowhead = {
    name: "target-arrowhead",
    args: {
      attrs: {
        d: "M -5,-5 5,-5 5,5 -5,5 Z",
        fill: "#fff",
        stroke: "#239edd",
        "stroke-width": 1,
      },
    },
  };
  // 边选中
  graph.on("edge:selected", (args) => {
    args.edge.addTools(["edge-editor", sourceArrowhead, targetArrowhead]);
  });
  // 边取消选中
  graph.on("edge:unselected", (args) => {
    setTimeout(() => {
      args.edge.removeTools(["edge-editor", sourceArrowhead, targetArrowhead]);
    }, 100);
  });

  // 控制连接桩显示/隐藏
  const showPorts = (ports: NodeListOf<SVGElement>, show: boolean) => {
    for (let i = 0, len = ports.length; i < len; i += 1) {
      ports[i].style.visibility = show ? "visible" : "hidden";
    }
  };
  graph.on(
    "node:mouseenter",
    ({
      _e,
      node,
    }: {
      _e: React.MouseEvent<HTMLDivElement, MouseEvent>;
      node: Node.Metadata;
    }) => {
      if (node.data?.isPage) return;

      const container = document.querySelector(`[data-cell-id="${node.id}"]`)!;
      if (!container) return;
      const ports = container.querySelectorAll(
        ".x6-port-body"
      ) as NodeListOf<SVGElement>;
      showPorts(ports, true);
    }
  );
  graph.on(
    "node:mouseleave",
    ({
      _e,
      node,
    }: {
      _e: React.MouseEvent<HTMLDivElement, MouseEvent>;
      node: Node.Metadata;
    }) => {
      if (node.data?.isPage) return;

      const container = document.querySelector("#graph-container")!;
      if (!container) return;
      const ports = container.querySelectorAll(
        ".x6-port-body"
      ) as NodeListOf<SVGElement>;
      showPorts(ports, false);
    }
  );

  // 处理添加节点事件 noCreate为不用创建节点
  graph.on("node:added", ({ node }) => {
    if (node.getData()?.noCreate) {
      setTimeout(() => {
        graph.removeNode(node.id);
      }, 50);
    }
  });
};

const getCellData = (cellData: Cell.Properties) => {
  const cellBasicData = getBasicData(cellData);
  const {
    id,
    zIndex,
    graphId,
    parent,
    position,
    shape,
    size,
    view,
    source,
    target,
    ports,
    labels
  } = cellData;

  const { attrs, data, router } = cellBasicData;
  return cellData.shape === "edge"
    ? // 边
      {
        zIndex,
        source,
        target,
        id,
        graphId,
        data,
        attrs,
        router,
        shape,
        labels,
      }
    : // 节点
      {
        id,
        graphId,
        parent,
        position,
        shape,
        size,
        view,
        zIndex,
        source,
        target,
        ports: ports?.items ? { items: ports.items } : undefined,
        data: cellBasicData,
      };
};

export const handleGraphApiEvent = (graph: Graph) => {
  let timer2: any;
  let map2: Record<string, any> = {};
  graph.on("cell:added", (args) => {
    if (args.cell?.data?.isPage) return;
    const data = args.cell.toJSON();
    const setData = () => {
      const id = args.cell.id;
      map2[id] = getCellData(data);
    };
    if (timer2) {
      setData();
      return;
    }
    setData();
    timer2 = setTimeout(() => {
      const graphId = sessionStorage.getItem("projectId");
      const list = Object.values(map2);
      if (graphId && list.length > 0) {
        BatchAddFlowchartElement(
          list.map((item) => {
            return {
              ...item,
              graphId,
            };
          })
        );
      }
      timer2 = null;
      map2 = {};
    }, 1000);
  });

  // 批量处理节点更新
  let timer1: any;
  let map: Record<string, any> = {};
  graph.on("cell:change:*", (args: EventArgs["cell:change:*"]) => {
    if (
      args.cell?.data?.isPage 
      || args.key === "tools" 
      || (timer2 && args.cell.shape !== 'edge' // 线可能在创建的时候不需要处理
    )) return;
    const setData = () => {
      const id = args.cell.id;
      const data = args.cell.toJSON();
      map[id] = getCellData(data);
    };
    if (timer1) {
      setData();
      return;
    }
    setData();
    timer1 = setTimeout(() => {
      const graphId = sessionStorage.getItem("projectId");
      const list = Object.values(map);
      if (graphId && list.length > 0) {
        BatchEditFlowchartElement(
          list.map((item) => {
            return {
              ...item,
              graphId,
            };
          })
        );
      }
      timer1 = null;
      map = {};
    }, 1000);
  });

  let timer: any;
  const ids: string[] = [];
  graph.on("cell:removed", (args) => {
    // 加入防抖 如果连续多个删除调用批量删除
    if (timer) {
      ids.push(args.cell.id);
      return;
    }
    ids.push(args.cell.id);
    timer = setTimeout(() => {
      timer = null;
      if (ids.length > 0) {
        BatchDeleteFlowchartElement({ ids });
      }
      ids.splice(0, ids.length);
    }, 500);
  });
};
