/**
 * Tree Layout - 树形图布局
 * 
 * 结构：
 *                 根节点
 *                    │
 *        ┌───────────┼───────────┐
 *        │           │           │
 *     子节点1     子节点2     子节点3
 *        │           │
 *    ┌───┴───┐       │
 *    │       │       │
 * 孙节点 孙节点   孙节点
 * 
 * 特点：
 * - 根节点在顶部
 * - 子节点向下展开
 * - 兄弟节点水平排列
 * - 经典的层级树形结构
 * 
 * 适用场景：
 * - 决策树
 * - 文件目录结构
 * - 分类体系
 */

import { LayoutEngine, layoutRegistry } from './LayoutEngine'
import type { Node, Point, IGraphModel } from '../core/types'

export class TreeLayout extends LayoutEngine {
  readonly type = 'tree' as const

  /** 默认配置 */
  protected config = {
    nodeSpacingX: 200,
    nodeSpacingY: 60,
    rootPosition: { x: 400, y: 50 },
    levelGap: 80,           // 层级垂直间距
    siblingGap: 60,         // 兄弟节点水平间距
    subtreeGap: 40          // 子树间距
  }

  layout(graph: IGraphModel): Map<string, Point> {
    const positions = new Map<string, Point>()
    const root = graph.root

    if (!root) return positions

    // 根节点位置（顶部）
    positions.set(root.id, { ...this.config.rootPosition })

    // 递归布局子节点
    this.layoutChildren(root, graph, positions, 0)

    return positions
  }

  /**
   * 计算子树宽度
   */
  private calcSubtreeWidth(
    node: Node,
    graph: IGraphModel,
    nodeWidth: number | undefined = undefined,
    gap: number = this.config.subtreeGap
  ): number {
    const effectiveWidth = nodeWidth ?? this.getNodeWidth(node)
    const children = graph.getChildren(node.id).filter(n => !n.hidden)
    if (children.length === 0) {
      return effectiveWidth
    }
    
    return children.reduce(
      (sum, child) => sum + this.calcSubtreeWidth(child, graph, undefined, gap) + gap,
      -gap  // 减去最后一个gap
    )
  }

  /**
   * 布局子节点
   */
  private layoutChildren(
    parent: Node,
    graph: IGraphModel,
    positions: Map<string, Point>,
    level: number
  ): void {
    const children = graph.getChildren(parent.id).filter(n => !n.hidden)
    if (children.length === 0) return

    const parentPos = positions.get(parent.id)
    if (!parentPos) return

    // 计算所有子节点的总宽度
    const totalWidth = children.reduce((sum, child) => {
      const subtreeWidth = this.calcSubtreeWidth(child, graph)
      return sum + subtreeWidth + this.config.subtreeGap
    }, -this.config.subtreeGap)

    // 子节点的起始X坐标
    let currentX = parentPos.x - totalWidth / 2

    // 子节点的Y坐标
    const childY = parentPos.y + this.config.levelGap

    children.forEach(child => {
      const subtreeWidth = this.calcSubtreeWidth(child, graph)
      const childX = currentX + subtreeWidth / 2

      positions.set(child.id, { x: childX, y: childY })

      // 递归布局孙节点
      this.layoutChildren(child, graph, positions, level + 1)

      currentX += subtreeWidth + this.config.subtreeGap
    })
  }
}

// 注册布局引擎
layoutRegistry.register(new TreeLayout())

export default TreeLayout
