import { StructureType, TopicType } from "@/enum";
import { MindMapProjectInfo, TopicItem, HierarchyResult } from "@/types";
import { Graph, Cell, Node } from "@antv/x6";
import TopicComponent from "@/components/mindMap/Topic";
import { topicData } from "@/config/data";
import { uuid } from "@/utils";
import { hierarchyMethodMap } from "@/pages/mindmap/hierarchy";
import { createEdge } from "./edge";
import { getTheme } from "./theme";
import { topicMenu } from "@/utils/contentMenu";

/**
 * 渲染思维导图项目
 * @param graph
 */
export const renderMindMap = (graph: Graph, setMindProjectInfo: () => void) => {
  const projectInfo = getMindMapProjectByLocal();
  if (!projectInfo) return;
  const { topics, pageSetting } = projectInfo;
  const cells: Cell[] = [];
  topics.forEach((topic) => {
    // 遍历出层次结构
    const result: HierarchyResult = hierarchyMethodMap[projectInfo.structure]?.(
      topic,
      pageSetting
    );

    let originPosition = { x: topic?.x ?? -10, y: topic?.y ?? -10 };
    if (graph.hasCell(topic.id)) {
      const node = graph.getCellById(topic.id);
      if (node.isNode()) {
        originPosition = node.position();
      }
    }
    const offsetX = originPosition.x - result.x;
    const offsetY = originPosition.y - result.y;

    const traverse = (hierarchyItem: HierarchyResult, parent?: Node) => {
      if (hierarchyItem) {
        const { data, children, x, y } = hierarchyItem;
        const id = data?.id || uuid();
        // 创建主题
        const node = graph.createNode({
          ...TopicComponent,
          width: data.width,
          height: data.height,
          data: {
            ...data,
            opacity: 100,
            // 节点内部执行数据更新方法
            setMindProjectInfo,
          },
          id,
          x: offsetX + x,
          y: offsetY + y,
          tools: [{
            name: 'contextmenu',
            args: {
              menu: topicMenu,
            },
          },]
        });
        cells.push(node);
        parent && parent.addChild(node);
        if(data?.links) {
          cells.push(...data.links.map(item => graph.createEdge(item)));
        }

        if (children) {
          children.forEach((item: HierarchyResult, index) => {
            const isBracket = [StructureType.leftBracket, StructureType.rightBracket].includes(projectInfo.structure)
            // 括号图不绘制中间连线
            if(!isBracket || (index === 0 || index === children.length - 1)) {
              const edge = createEdge(
                graph,
                id,
                item,
                projectInfo.structure,
                projectInfo.theme
              );
              cells.push(edge);
              node.addChild(edge);
            }
            // 递归遍历
            traverse(item, node);
          });
        }
      }
    };

    traverse(result);
  });

  const oldCells = graph.getCells();
  // 移除不要的节点及对应的边
  oldCells.forEach((cell) => {
    if (!cells.find((item) => cell.id === item.id)) {
      graph.removeCell(cell.id + "-edge");
      graph.removeCell(cell);
    }
  });
  // 添加或删除节点
  cells
    .filter((cell) => cell.isNode() && !graph.hasCell(cell.id))
    .forEach((cell) => {
      graph.addCell(cell);
    });
  // 更新老的节点
  cells
    .filter((cell) => cell.isNode() && graph.hasCell(cell.id))
    .forEach((cell) => {
      cell.isNode() && updateNode(cell, graph);
    });
  // 添加所需的节点
  cells
    .filter((cell) => cell.isEdge())
    .forEach((cell) => {
      graph.addCell(cell);
    });
};

const updateNode = (node: Node, graph: Graph) => {
  const oldCell = graph.getCellById(node.id);
  if(oldCell.isNode()) {
    oldCell.setData(node.data);
    oldCell.position(node.position().x, node.position().y);
    // oldCell.setAttrs(node.attrs);
    // const cells = node.children?.map(item => graph.getCellById(item.id));
    // oldCell.setChildren(cells ?? null);
  }
}

/**
 * 添加分支主题
 */
export const addTopic = (
  type: TopicType,
  setMindProjectInfo: (info: MindMapProjectInfo) => void,
  node?: Node,
  otherData: Record<string, any> = {}
): TopicItem | undefined => {
  const projectInfo = getMindMapProjectByLocal();
  if (!projectInfo || !setMindProjectInfo) return;

  const topic = buildTopic(
    type,
    {
      ...(otherData || {}),
      parentId: node?.id,
    },
    node
  );

  if (node) {
    const parentId = node.id;
    const traverse = (topics: TopicItem[]) => {
      topics.forEach((item) => {
        if (item.id === parentId) {
          if (item.children) {
            item.children?.push(topic);
          } else {
            item.children = [topic];
          }
        }
        if (item.children) {
          traverse(item.children);
        }
      });
    };
    traverse(projectInfo?.topics || []);
  } else {
    projectInfo.topics.push(topic);
  }

  setMindProjectInfo(projectInfo);
  return topic;
};

const topicMap = {
  [TopicType.main]: {
    label: "中心主题",
    width: 206,
    height: 70,
  },
  [TopicType.branch]: {
    label: "分支主题",
    width: 104,
    height: 40,
  },
  [TopicType.sub]: {
    label: "子主题",
    width: 76,
    height: 27,
  },
};

/**
 * 构建一个主题数据
 * @param type 主题类型
 * @param options 配置项
 * @returns
 */
export const buildTopic = (
  type: TopicType,
  options: Record<string, any> = {},
  parentNode?: Node
): TopicItem => {
  const projectInfo = getMindMapProjectByLocal();

  const theme = getTheme(
    projectInfo?.theme,
    type === TopicType.sub ? parentNode : undefined
  );
  const id = uuid();
  return {
    ...topicData,
    id,
    type,
    label: topicMap[type].label || "自由主题",
    width: topicMap[type].width || 206,
    height: topicMap[type].height || 70,
    fill: {
      ...topicData.fill,
      ...theme[type]?.fill,
    },
    text: {
      ...topicData.text,
      ...theme[type]?.text,
    },
    stroke: {
      ...topicData.stroke,
      ...theme[type]?.stroke,
    },
    edge: {
      ...topicData.edge,
      color: theme[type]?.edge.color,
    },
    ...options,
    children: (options?.children || topicData.children || []).map((item: TopicItem) => {
      return {
        ...item,
        parentId: id
      }
    })
  };
};

/**
 * 从本地获取项目信息
 * @returns
 */
export const getMindMapProjectByLocal = (): MindMapProjectInfo | null => {
  return JSON.parse(localStorage.getItem("minMapProjectInfo") || "null");
};

/**
 * 更新主题数据
 * @param id 主题id
 * @param value 更新的数据
 * @param setMindProjectInfo 更新项目信息方法
 */
export const updateTopic = (
  id: string,
  value: Partial<TopicItem>,
  setMindProjectInfo: (info: MindMapProjectInfo) => void
) => {
  const projectInfo = getMindMapProjectByLocal();
  if (!projectInfo || !setMindProjectInfo) return;

  const traverse = (topics: TopicItem[]) => {
    topics.forEach((item) => {
      if (item.id === id) {
        Object.assign(item, value);
      }
      if (item.children) {
        traverse(item.children);
      }
    });
  };

  traverse(projectInfo?.topics || []);
  setMindProjectInfo(projectInfo);
};
