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 TopicBorder from "@/components/mindMap/Border";
import SummaryBorder from "@/components/mindMap/SummaryBorder";
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";
import {
  cacluculateExtremeValue,
  getBorderPositionAndSize,
} from "@/utils/mindmapHander";

/**
 * 渲染思维导图项目
 * @param graph
 */
export const renderMindMap = ({
  topics,
  pageSetting,
  structure,
  theme,
  graph,
  setMindProjectInfo,
  returnCells = false
}: {
  topics: TopicItem[];
  pageSetting: MindMapProjectInfo["pageSetting"];
  structure: StructureType;
  theme: string;
  graph: Graph;
  setMindProjectInfo: (info: MindMapProjectInfo) => void;
  returnCells?: boolean;
}) => {
  const cells: Cell[] = [];
  topics.forEach((topic) => {
    // 遍历出层次结构
    const result: HierarchyResult = hierarchyMethodMap[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,
              },
            },
          ],
        });
        // 渲染边框
        if (data.border) {
          cells.push(
            createBorderComponent(hierarchyItem, offsetX, offsetY, graph)
          );
        }
        // 渲染概要
        if (data.summary) {
          const summaryCells = createSummaryCells(
            hierarchyItem,
            data.summary,
            structure,
            pageSetting,
            theme,
            graph,
            setMindProjectInfo,
            offsetX,
            offsetY
          );
          cells.push(...(summaryCells || []));
        }
        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(structure);
            // 括号图不绘制中间连线
            if (!isBracket || index === 0 || index === children.length - 1) {
              const edge = createEdge(graph, id, item, structure, theme, {
                onlyOneChild: children.length === 1,
              });
              cells.push(edge);
              node.addChild(edge);
            }
            // 递归遍历
            traverse(item, node);
          });
        }
      }
    };

    traverse(result);
  });
  if(returnCells) return cells;
  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);
    });
  // 添加所需的节点
  const edgeCells = cells.filter((cell) => cell.isEdge());
  graph.removeCells(edgeCells);
  graph.addCell(edgeCells);
};

// 渲染概要
const createSummaryCells = (
  hierarchyItem: HierarchyResult, 
  summary: TopicItem['summary'],
  structure: StructureType,
  pageSetting: MindMapProjectInfo['pageSetting'],
  theme: string,
  graph: Graph,
  setMindProjectInfo: (info: MindMapProjectInfo) => void,
  offsetX: number,
  offsetY: number
): Cell[] => {
  let cells: Cell[] = [];
  if (summary) {
    const positionAndSize = cacluculateExtremeValue(
      hierarchyItem,
      hierarchyItem.children
    );
    const totalHeight = positionAndSize.maxY - positionAndSize.minY;
    const totalWidth = positionAndSize.maxX - positionAndSize.minX;

    // 概要边框
    const node = graph.createNode({
      ...SummaryBorder,
      data: summary.border,
      id: summary.topic.id + "-border",
      zIndex: 0,
      position: {
        x: offsetX + positionAndSize.minX - 2,
        y: offsetY + positionAndSize.minY - 2,
      },
      size: {
        width: totalWidth + 4,
        height: totalHeight + 4,
      },
    });
    cells.push(node);

    // 概要节点
    cells.push(...renderMindMap({
      topics: [{
        ...summary.topic,
        x: offsetX + hierarchyItem.x + totalWidth + 40,
        y: offsetY + hierarchyItem.y
      }],
      pageSetting,
      structure,
      theme,
      graph,
      setMindProjectInfo,
      returnCells: true
    }) || []);
  }
  return cells;
}

// 创建外框组件
const createBorderComponent = (
  hierarchyItem: HierarchyResult,
  offsetX: number,
  offsetY: number,
  graph: Graph
) => {
  const positionAndSize = getBorderPositionAndSize(hierarchyItem);
  return graph.createNode({
    ...TopicBorder,
    id: hierarchyItem.id + "-border",
    data: {
      ...hierarchyItem.data.border,
      origin: hierarchyItem.id,
    },
    zIndex: 0,
    position: {
      x: offsetX + positionAndSize.x,
      y: offsetY + positionAndSize.y,
    },
    size: {
      width: positionAndSize.width,
      height: positionAndSize.height,
    },
  });
};

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.setSize(node.size().width, node.size().height);
    // 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,
      isSummary: node?.data?.isSummary,
      summarySource: node?.data?.summarySource
    },
    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);
        }
        if (item.summary) {
          traverse([item.summary.topic])
        }
      });
    };
    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);
};
