import { Cell, Graph } from "@antv/x6";
import { useRef, useState } from "react";
import { Dnd } from "@antv/x6-plugin-dnd";
import { Transform } from "@antv/x6-plugin-transform";
import { Snapline } from "@antv/x6-plugin-snapline";
import { Clipboard } from "@antv/x6-plugin-clipboard";
import { Selection } from "@antv/x6-plugin-selection";
import { History } from "@antv/x6-plugin-history";
import { Scroller } from "@antv/x6-plugin-scroller";
import { Keyboard } from "@antv/x6-plugin-keyboard";
import { Export } from "@antv/x6-plugin-export";
import { WorkFlow } from "./interface";
import { nodeItems } from "@/components/nodes";
import { bindEvent } from "./event";
import { bindFastKey } from "./fastkey";
import dayjs from "dayjs";
import { NodeType } from "@/enum";

type ModeType = "edit" | "ops";
export default function flowModel() {
  const graphRef = useRef<Graph>();
  const [graph, setGraph] = useState<Graph>();
  // 工作流信息
  const [workflow, setWorkflow] = useState<WorkFlow>();
  const [saveInfo, setSaveInfo] = useState<string>();
  const [mode, setMode] = useState<ModeType>("edit");

  // 初始化设计器
  const init = (container: HTMLDivElement, mode: ModeType = "edit") => {
    setMode(mode);
    graphRef.current?.dispose();
    const instance = new Graph({
      container,
      width: container.clientWidth,
      height: container.clientHeight,
      autoResize: true,
      panning: false,
      // 鼠标滚轮缩放
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: "ctrl",
        minScale: 0.2,
        maxScale: 2,
      },
      background: {
        color: "#eee",
      },
      grid: {
        size: 20,
        type: "dot",
        visible: true,
        args: { background: true },
      },
      // 节点交互
      interacting:
        mode === "ops"
          ? false
          : {
              edgeLabelMovable: false,
              edgeMovable: true,
              nodeMovable: (view) => {
                // 节点上锁状态无法移动
                const data = view.cell.getData<{ lock: boolean }>();
                return !data?.lock;
              },
              arrowheadMovable: true,
              vertexMovable: true,
              vertexAddable: true,
              vertexDeletable: true,
              useEdgeTools: true,
              magnetConnectable: true,
              stopDelegateOnDragging: true,
              toolsAddable: true,
            },
      // 连线配置
      connecting: {
        snap: true,
        allowLoop: true,
        allowPort: false,
        allowNode: false,
        allowMulti: false,
      },
    });

    // 对齐线
    instance.use(
      new Snapline({
        enabled: true,
      })
    );

    // 框选
    instance.use(
      new Selection({
        enabled: true,
        multiple: true,
        rubberband: false,
        movable: false,
        showNodeSelectionBox: false,
        // showEdgeSelectionBox: true,
        pointerEvents: "none",
        strict: false,
      })
    );

    // 历史记录
    instance.use(
      new History({
        enabled: false,
      })
    );

    // 滚动
    instance.use(
      new Scroller({
        enabled: true,
        autoResize: true,
        pannable: true,
      })
    );

    // 快捷键
    instance.use(new Keyboard());

    setGraph(instance);
    graphRef.current = instance;

    if (mode === "edit") {
      bindEvent(instance, doRequest);
      bindFastKey(instance);
    }
  };

  // 加载设计
  const loadWorkflow = (info: WorkFlow) => {
    if (!graph) return;

    setWorkflow(info);
    // 渲染工作流
    let cells: Cell[] = [];
    // 节点
    [...info.nodes, ...info.objects].forEach((item) => {
      const shape = nodeItems.find((obj) => obj.key === item.type)?.name;
      const node = graph.createNode({
        id: item.id,
        shape: shape || "notice-node",
        position: {
          x: item.x,
          y: item.y,
        },
        data: {
          ...item,
        },
      });
      if (item.type === NodeType.TEXT) {
        node?.size(item.width, item.height);
      }
      node && cells.push(node);
    });
    // 线
    info.lines.forEach((item) => {
      const sourceNode = cells.find((obj) => obj.id === item.startNodeId);
      const targetNode = cells.find((obj) => obj.id === item.endNodeId);
      // @ts-ignore
      const sourcePorts = sourceNode?.getPorts();
      const sourcePort = sourcePorts?.find((i: any) => i.group === "right");
      // @ts-ignore
      const targetPorts = targetNode?.getPorts();
      const targetPort = targetPorts?.find((i: any) => i.group === "left");

      if (!sourcePort || !targetPort) return;

      const line = graph.createEdge({
        id: item.id,
        source: {
          cell: sourceNode ? sourceNode.id : item.startNodeId,
          port: sourcePort.id,
        },
        target: {
          cell: targetNode ? targetNode.id : item.endNodeId,
          port: targetPort.id,
        },
        router: {
          name: "manhattan",
          args: {
            padding: 20,
            excludeShapes: ["notice-node"],
          },
        },
        zIndex: 0,
        connector: { name: "rounded", args: {} },
        attrs: {
          line: {
            stroke: "#7e8186",
            strokeWidth: 2,
          },
        },
        data: {
          ...item,
        },
      });
      line && cells.push(line);
    });

    graph.resetCells(cells);
    graph.toggleHistory(true);
  };

  const doRequest = (service: (params: any) => Promise<any>, params: any) => {
    setSaveInfo("保存中...");
    try {
      return service(params).then((res) => {
        setSaveInfo(`自动保存 ${dayjs().format("HH:mm:ss")}`);
        return res;
      });
    } catch (error) {
      setSaveInfo(`保存失败 ${dayjs().format("HH:mm:ss")}`);
    }
  };

  return {
    init,
    graph,
    workflow,
    loadWorkflow,
    setWorkflow,
    saveInfo,
    doRequest,
    mode,
  };
}
