/**
 * Timeline Vertical Layout - 纵向时间轴布局
 * 
 * 结构：
 * 
 *   Detail1 ─── ● ─── Detail2
 *               │
 *           Event1
 *               │
 *   Detail3 ─── ● ─── Detail4
 *               │
 *           Event2
 *               │
 *             ...
 *
 * 特点：
 * - 主节点沿垂直时间轴均匀排列
 * - 子节点在时间轴左侧或右侧交替展开
 * - 连线使用正交折线，清晰规范
 * - 强调时间顺序和进程
 * 
 * 适用场景：
 * - 项目计划/里程碑
 * - 历史事件
 * - 流程步骤
 */

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

export class TimelineVerticalLayout extends LayoutEngine {
  readonly type = 'timeline-vertical' as const

  /** 默认配置 */
  protected config = {
    nodeSpacingX: 200,
    nodeSpacingY: 60,
    rootPosition: { x: 300, y: 80 },
    mainNodeGap: 120,       // 主节点间距（时间轴上）
    subNodeGap: 50,         // 子节点水平间距
    branchOffset: 150,      // 子节点到时间轴的距离
    nodeHeight: 36          // 节点高度
  }

  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 })

    // 获取一级子节点（主时间节点）
    const mainNodes = graph.getChildren(root.id).filter(n => !n.hidden)

    if (mainNodes.length === 0) return positions

    this.layoutMainNodes(mainNodes, graph, positions)

    return positions
  }

  /**
   * 布局主时间节点及其后代
   */
  private layoutMainNodes(
    mainNodes: Node[],
    graph: IGraphModel,
    positions: Map<string, Point>
  ): void {
    const rootPos = positions.get(graph.root!.id)!
    const timelineX = rootPos.x  // 时间轴的 X 坐标

    mainNodes.forEach((node, index) => {
      // 主节点位置：沿垂直时间轴排列
      const mainX = timelineX
      const mainY = rootPos.y + (index + 1) * this.config.mainNodeGap

      positions.set(node.id, { x: mainX, y: mainY })

      // 获取子节点
      const children = graph.getChildren(node.id).filter(n => !n.hidden)
      if (children.length === 0) return

      // 子节点交替分布在左、右侧
      children.forEach((child, childIndex) => {
        // 交替左右：偶数索引在左侧，奇数索引在右侧
        const isLeft = childIndex % 2 === 0
        const direction = isLeft ? -1 : 1
        
        // 子节点 Y 坐标：在主节点同一水平线上
        const childY = mainY
        
        // 子节点 X 坐标：从时间轴向左右延伸
        const childX = timelineX + direction * this.config.branchOffset

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

        // 递归布局后代节点
        this.layoutDescendants(child, graph, positions, childX, childY, direction)
      })
    })
  }

  /**
   * 递归布局后代节点
   * 后代节点继续向远离时间轴的方向延伸
   */
  private layoutDescendants(
    node: Node,
    graph: IGraphModel,
    positions: Map<string, Point>,
    parentX: number,
    parentY: number,
    direction: -1 | 1
  ): void {
    const children = graph.getChildren(node.id).filter(n => !n.hidden)
    if (children.length === 0) return

    const nodeGap = this.config.subNodeGap + this.getNodeWidth(node)  // 节点中心之间的间距

    // 子节点沿 direction 方向（远离时间轴）依次排列
    // 多个子节点时，按 index 依次向外延伸
    children.forEach((child, index) => {
      // 子节点 Y 坐标保持不变（与父节点同一水平线）
      const childY = parentY
      
      // 子节点 X 坐标：从父节点沿 direction 方向延伸
      // 每个子节点依次向外排列
      const childX = parentX + direction * nodeGap * (index + 1)

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

      // 递归布局更深层
      this.layoutDescendants(child, graph, positions, childX, childY, direction)
    })
  }
}

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

export default TimelineVerticalLayout
