///|
// Details and summary element pruning helpers.

///|
fn clone_node_with_children(
  node : @node.Node,
  children : Array[@node.Node],
) -> @node.Node {
  @node.Node::with_uid_and_measure(
    node.id,
    node.uid,
    node.style,
    children,
    node.measure,
    node.text,
  )
}

///|
fn find_first_summary_path_in_node(node : @node.Node) -> Array[Int]? {
  if node_id_is_tag(node.id, "summary") {
    return Some([])
  }
  for i = 0; i < node.children.length(); i = i + 1 {
    match find_first_summary_path_in_node(node.children[i]) {
      Some(path) => {
        let prefixed : Array[Int] = [i]
        for segment in path {
          prefixed.push(segment)
        }
        return Some(prefixed)
      }
      None => ()
    }
  }
  None
}

///|
fn find_first_summary_path_in_children(
  children : Array[@node.Node],
) -> (Int, Array[Int])? {
  for i = 0; i < children.length(); i = i + 1 {
    match find_first_summary_path_in_node(children[i]) {
      Some(path) => return Some((i, path))
      None => ()
    }
  }
  None
}

///|
fn prune_node_to_summary_path(
  node : @node.Node,
  path : Array[Int],
) -> @node.Node {
  if path.length() == 0 {
    return node
  }
  let next_index = path[0]
  if next_index < 0 || next_index >= node.children.length() {
    return node
  }
  let remaining : Array[Int] = []
  for i = 1; i < path.length(); i = i + 1 {
    remaining.push(path[i])
  }
  let kept_child = prune_node_to_summary_path(
    node.children[next_index],
    remaining,
  )
  let kept_children : Array[@node.Node] = []
  for i = 0; i < next_index; i = i + 1 {
    let sibling = node.children[i]
    if sibling.id == "#text" {
      match sibling.text {
        Some(text) if !text.is_empty() && text.trim().is_empty() =>
          kept_children.push(sibling)
        _ => ()
      }
    }
  }
  kept_children.push(kept_child)
  clone_node_with_children(node, kept_children)
}

///|
fn prune_closed_details_children(
  children : Array[@node.Node],
) -> Array[@node.Node] {
  match find_first_summary_path_in_children(children) {
    Some((top_index, path)) => {
      let pruned_top = prune_node_to_summary_path(children[top_index], path)
      [pruned_top]
    }
    None => []
  }
}