import { Graph, Node } from "@antv/x6";
import { useEffect, useRef } from "react";
import { LaneItem, StageItem } from "@/types";
export const useLane = (node: Node, graph: Graph) => {
  const { lane, stage, stageWidth, stroke, headerHeight, direction } =
    node.getData<{
      lane: LaneItem[];
      stage: StageItem[];
      headerHeight: number;
      stageWidth: number;
      stroke: { width: number };
      direction: "vertical" | "horizontal";
    }>();
  const strokeWidth = stroke.width;
  const lister = useRef<any>();

  // 监听泳变化
  useEffect(() => {
    let width = node.getSize().width;
    let height = node.getSize().height;

    if (lane.length) {
      if (direction === "vertical") {
        width = lane.reduce(
          (a: number, b: LaneItem) => a + b.width + strokeWidth,
          0
        );
      } else {
        height = lane.reduce(
          (a: number, b: LaneItem) => a + b.width + strokeWidth,
          0
        );
      }
    }
    if (stage.length) {
      if (direction === "vertical") {
        width += stageWidth;
      } else {
        height += stageWidth;
      }
    }

    node.setSize({ width, height });
  }, [lane.length]);

  // 监听宽高变化
  if (!lister.current) {
    lister.current = node.on("change:size", (args) => {
      const { lane, stage, direction } = node.data;
      // 更新泳道宽度
      if (lane.length) {
        const originWidth = lane.reduce(
          (a: number, b: LaneItem) => a + b.width,
          0
        );
        const offset =
          (direction === "vertical"
            ? args?.current?.width || 0
            : args?.current?.height || 0) -
          originWidth -
          (stage.length ? stageWidth : 0);
        console.log(offset )
        if (offset) {
          node.setData({
            lane: lane.map((item: LaneItem) => {
              return {
                ...item,
                width: item.width + offset / lane.length - strokeWidth,
              };
            }),
          });
        }
      }
      // 更新阶段高度
      if (stage.length) {
        const originHeight = stage.reduce(
          (a: number, b: StageItem) => a + b.height,
          0
        );
        const offset =
          (direction === "vertical"
            ? args?.current?.height || 0
            : args?.current?.width || 0) -
          originHeight -
          headerHeight;

        if (offset) {
          node.setData({
            stage: stage.map((item: StageItem) => {
              return {
                ...item,
                height: item.height + offset / stage.length - strokeWidth,
              };
            }),
          });
        }
      }
    });
  }

  // 插入阶段
  const handleInsertStage = (x: number, y: number) => {
    const stage = node.data.stage || [];
    const { width, height } = node.getSize();
    // 新阶段位置
    const h1 =
      direction === "vertical"
        ? y - node.getPosition().y - headerHeight
        : x - node.getPosition().x - headerHeight;
    // 无阶段 从中切开
    if (!stage.length) {
      const h2 = direction === "vertical"
      ? height - h1 - headerHeight
      : width - h1 - headerHeight;
      node.setData({
        stage: [
          {
            name: "阶段",
            height: h1,
          },
          {
            name: "阶段",
            height: h2,
          },
        ],
      });
      node.setSize({
        width: width + (direction === "vertical" ? stageWidth : 0),
        height: height + (direction === "horizontal" ? stageWidth : 0),
      });
    } else {
      // 有阶段 则找出在哪一段内 再分成两段
      let temp = 0; // 记录长度
      for (let i = 0; i < stage.length; i++) {
        const item = stage[i];
        temp += item.height;
        if (temp > h1) {
          // 插入
          const h3 = temp - h1;
          const h4 = item.height - h3;
          const newStages = [
            {
              name: "阶段",
              height: h4,
            },
            {
              ...item,
              height: h3,
            },
          ];
          stage.splice(i, 1, ...newStages);
          node.setData(
            {
              stage: [...stage],
            },
            {
              deep: false,
            }
          );
          break;
        }
      }
    }
  };

  // 插入泳道
  const handleInsertLane = (x: number, y: number) => {
    const lane = node.data.lane || [];
    const stage = node.data.stage || [];
    if (!lane.length) {
      node.setData({
        lane: [
          {
            name: "",
            width: direction === "vertical" 
            ? node.getSize().width - (stage.length ? stageWidth : 0)
            : node.getSize().height - (stage.length ? stageWidth : 0),
          },
        ],
      });
    } else {
      // 判断在哪一个泳道内
      let temp = 0;
      const w1 = direction === "vertical" 
        ? x - node.getPosition().x
        : y - node.getPosition().y;
      for (let i = 0; i < lane.length; i++) {
        const item = lane[i];
        temp += item.width;
        if (temp > w1) {
          // 插入
          lane.splice(i, 0, {
            name: "",
            width: lane[lane.length - 1].width,
          });
          node.setData({
            lane: [...lane],
          });
          break;
        }
      }
    }
  };

  const listerEmbedded = useRef<any>();
  if (!listerEmbedded.current) {
    listerEmbedded.current = graph.on("node:embedded", (args) => {
      const { isSeparator, isLane, separatorDiration, laneDirection } =
        args.node.data || {};
      const { direction } = node.data;
      // 分隔符
      if (isSeparator && separatorDiration !== direction) {
        const bbox = node.getBBox();
        if (bbox.isIntersectWithRect(args.node.getBBox())) {
          handleInsertStage(args.x, args.y);
        }
      }
      // 泳道
      if (isLane && laneDirection === direction) {
        const bbox = node.getBBox();
        if (bbox.isIntersectWithRect(args.node.getBBox())) {
          handleInsertLane(args.x, args.y);
        }
      }
    });
  }

  const handleChangeLane = (val: number | null) => {
    if (!val) {
      node.setData({ lane: [] }, { deep: false });
      return;
    }
    const currentLanes = node.data.lane || [];
    const currentLength = currentLanes.length;
    const { direction } = node.data;

    if (currentLength < val) {
      let width = direction === "vertical" ? node.getSize().width : node.getSize().height;
      if (currentLength > 0) {
        width = currentLanes[currentLength - 1].width;
      }
      const newLanes = new Array(val - currentLength).fill({ width, name: "" });
      node.setData({ lane: [...(node.data.lane || []), ...newLanes] });
    } else {
      node.updateData({
        lane: currentLanes.slice(0, val),
      });
    }
  };

  return {
    handleChangeLane,
  };
};
