/**
 * 图形布局模块
 * 
 * 该模块提供了一系列用于处理 ReactFlow 图形布局的工具和算法。
 * 支持多种布局算法,包括原始布局、树形布局、层次布局等。
 * 主要用于自动计算和调整图形中节点和边的位置。
 */

import { ReactFlowGraph } from "../../types";
import { removeEmpty } from "../../utils/base";
import { D3DAGLayoutAlgorithms, kD3DAGAlgorithms } from "./algorithms/d3-dag";
import { layoutD3Hierarchy } from "./algorithms/d3-hierarchy";
import { layoutDagreTree } from "./algorithms/dagre-tree";
import { ELKLayoutAlgorithms, kElkAlgorithms } from "./algorithms/elk";
import { layoutOrigin } from "./algorithms/origin";

/**
 * 布局方向类型
 * vertical: 垂直布局
 * horizontal: 水平布局
 */
export type LayoutDirection = "vertical" | "horizontal";

/**
 * 布局可见性类型
 * visible: 可见
 * hidden: 隐藏
 */
export type LayoutVisibility = "visible" | "hidden";

/**
 * 布局间距配置接口
 * x: 水平间距
 * y: 垂直间距
 */
export interface LayoutSpacing {
    x: number;
    y: number;
}

/**
 * ReactFlow 布局配置接口
 * 定义了布局所需的各项参数
 */
export type ReactFlowLayoutConfig = {
    algorithm: LayoutAlgorithms;        // 使用的布局算法
    direction: LayoutDirection;          // 布局方向
    spacing: LayoutSpacing;             // 节点间距
    /**
     * 布局可见性配置
     * 在首次布局时如果节点大小不可用,可能需要隐藏布局
     */
    visibility: LayoutVisibility;
    /**
     * 是否反转源节点手柄顺序
     */
    reverseSourceHandles: boolean;
    autoCenterRoot: boolean
};

/**
 * 布局算法所需的属性类型
 * 继承自 ReactFlowGraph 并包含布局配置(除算法外)
 */
export type LayoutAlgorithmProps = ReactFlowGraph &
    Omit<ReactFlowLayoutConfig, "algorithm">;

/**
 * 布局算法函数类型定义
 * 接收布局属性作为参数,返回布局后的图形数据
 */
export type LayoutAlgorithm = (
    props: LayoutAlgorithmProps
) => Promise<ReactFlowGraph | undefined>;

/**
 * 可用的布局算法映射表
 * 包含所有支持的布局算法实现
 */
export const layoutAlgorithms: Record<string, LayoutAlgorithm> = {
    origin: layoutOrigin,
    "dagre-tree": layoutDagreTree,
    "d3-hierarchy": layoutD3Hierarchy,
    ...kElkAlgorithms,
    ...kD3DAGAlgorithms,
};

/**
 * 默认布局配置
 */
export const defaultLayoutConfig: ReactFlowLayoutConfig = {
    algorithm: "dagre-tree",           // 默认使用 elk-mr-tree 算法
    direction: "horizontal",              // 默认垂直布局
    visibility: "visible",              // 默认可见
    spacing: { x: 120, y: 120 },       // 默认间距
    reverseSourceHandles: false,        // 默认不反转源节点手柄
    autoCenterRoot: false
};

/**
 * 支持的布局算法类型联合
 */
export type LayoutAlgorithms =
    | "origin"
    | "dagre-tree"
    | "d3-hierarchy"
    | ELKLayoutAlgorithms
    | D3DAGLayoutAlgorithms;

/**
 * ReactFlow 布局类型
 * 包含图形数据和可选的布局配置
 */
export type ReactFlowLayout = ReactFlowGraph & Partial<ReactFlowLayoutConfig>;

/**
 * 执行 ReactFlow 图形布局的主函数
 * 
 * @param options - 布局选项,包含图形数据和布局配置
 * @returns 返回布局后的图形数据
 * 
 * 函数流程:
 * 1. 合并默认配置和用户配置
 * 2. 获取对应的布局算法
 * 3. 执行布局计算
 * 4. 如果布局失败,回退到原始布局
 */
export const layoutReactFlow = async (
    options: ReactFlowLayout
): Promise<ReactFlowGraph> => {
    // 合并配置,移除空值
    const config = { ...defaultLayoutConfig, ...removeEmpty(options) };
    const { nodes = [], edges = [] } = config;

    // 获取并执行布局算法
    const layout = layoutAlgorithms[config.algorithm];
    let result = await layout({ ...config, nodes, edges });

    // 布局失败时回退处理
    if (!result) {
        result = await layoutReactFlow({
            ...config,
            nodes,
            edges,
            algorithm: "origin",
        });
    }
    return result!;
};