import { ComponentMapNode } from "../generators/interface"

export interface NeedBuildNode {
  displayName: string
  $parentNode: string
  $childrenNode: string[]
  [key: string]: unknown
}

interface BuildedNode {
  displayName: string
  $parentNode: string
  $childrenNode: BuildedNode[]
  [key: string]: unknown
}

export function buildForest(
  nodes: NeedBuildNode[],
  layoutInfos: Record<string, ComponentMapNode>,
): BuildedNode[] {
  const builtNodes: { [key: string]: BuildedNode } = {}
  const calcContext: Record<string, NeedBuildNode> = {}
  const needBuildNode = nodes.map((node) => {
    const mixedNode = {
      ...node,
      $parentNode: layoutInfos[node.displayName].parentNode,
      $childrenNode: layoutInfos[node.displayName].childrenNode,
    }
    calcContext[node.displayName] = mixedNode
    return mixedNode
  })

  function buildNode(node: NeedBuildNode): BuildedNode {
    if (builtNodes[node.displayName]) {
      return builtNodes[node.displayName]
    }

    const children: BuildedNode[] = (node.$childrenNode || []).map(
      (childName) => {
        const childNode = calcContext[childName]
        return buildNode(childNode)
      },
    )

    const builtNode: BuildedNode = {
      ...node,
      displayName: node.displayName,
      $parentNode: node.$parentNode,
      $childrenNode: children
    }

    builtNodes[node.displayName] = builtNode

    return builtNode
  }

  const forest: BuildedNode[] = needBuildNode
    .filter((node) => !calcContext[node.$parentNode])
    .map((rootNode) => buildNode(rootNode))

  return forest
}
