fastdf <- function (list) {
  rows <- unique(unlist(lapply(list, NROW)))
  stopifnot(length(rows) == 1)
  class(list) <- "data.frame"
  attr(list, "row.names") <- c(NA_integer_, -rows)
  list
}

addDepType <- function(p, type = c("Imports", "Depends", "LinkingTo", "Suggests"), pdb) {
  if (!p %in% rownames(pdb)) {
    fastdf(list(
      dep = character(0),
      package = character(0),
      type = character(0)
    ))

  } else {
    x <- cleanPkgField(pdb[p, type])
    fastdf(list(
      dep = x,
      package = rep(p, length(x)),
      type = rep(type, length(x))
    ))
  }
}


#' Create dependency graph from available packages.
#'
#' Each package is a node, and a dependency is an edge
#'
#' @inheritParams pkgDep
#' @inheritParams makeRepo
#'
#' @export
#' @family dependency functions
#'
#' @seealso [pkgDep()] to extract package dependencies
#'
#' @example /inst/examples/example_makeDepGraph.R
makeDepGraph <- function(
  pkg, availPkgs, repos = getOption("repos"), type = "source",
  suggests = TRUE, enhances = FALSE,
  includeBasePkgs = FALSE, ...)
{

  if (missing(availPkgs)) {
    availPkgs <- pkgAvail(repos = repos, type = type)
  }
  pkgs <- availPkgs
  rownames(pkgs) <- as.vector(pkgs[, "Package"])
  allPkgs <- rownames(pkgs)
  if (!length(allPkgs))
    stop("no packages in specified repositories")



  pkgEdge <- function(p, type = c("Imports", "Depends", "LinkingTo"), pdb) {
    do.call(rbind, lapply(type, function(t)addDepType(p, t, pdb = pdb)))
  }
  pkgEdges <- function(pp, type = c("Imports", "Depends", "LinkingTo"), pdb) {
    do.call(rbind, lapply(pp, pkgEdge, type = type, pdb = pdb))
  }

  # Build depends edge list for original pkg list, combined with top level suggests

  pkg_orig <- pkg

  if (suggests) {
    edges1 <- pkgEdges(pkg, type = c("Suggests"), availPkgs)
    p_sug <- unique(unlist(
      tools::package_dependencies(pkg, db = availPkgs,
                                  which = "Suggests", recursive = FALSE)
    ))
    pkg <- unique(c(p_sug, pkg))
  }

  if (enhances) {
    edges2 <- pkgEdges(pkg_orig, type = c("Enhances"), availPkgs)
    p_enh <- unique(unlist(
      tools::package_dependencies(pkg_orig, db = availPkgs,
                                  which = "Enhances", recursive = FALSE)
    ))
    pkg <- unique(c(p_enh, pkg))
  }
  p_dep <- unique(unlist(
                  tools::package_dependencies(
                    pkg, db = availPkgs,
                    which = c("Imports", "Depends", "LinkingTo"), recursive = TRUE)
  ))
  pkg <- unique(c(p_dep, pkg))

  edges <- pkgEdges(pkg, type = c("Imports", "Depends", "LinkingTo"), availPkgs)

  if (suggests) {
    edges <- rbind(edges, edges1)
  }
  if (enhances) {
    edges <- rbind(edges, edges2)
  }
  nedges <- nrow(edges)
  if (nedges && !includeBasePkgs)
    edges <- edges[!(edges[["dep"]] %in% basePkgs()), ]

  vert <- unique(c(pkg_orig, edges[["dep"]], edges[["package"]]))
  ret <- igraph::graph_from_data_frame(d = edges, directed = TRUE, vertices = vert)
  class(ret) <- c("pkgDepGraph", "igraph")
  attr(ret, "pkgs") <- pkg_orig
  ret
}
