# NAMESPACE roclet: reads @export / @exportS3Method / @exportClass /
# @exportMethod / @import / @importFrom / @useDynLib tags from every
# block (not grouped by topic, since several functions under the same
# @rdname can each need their own export).

namespace_roclet_build <- function(blocks) {
  exports <- character()
  s3methods <- character()
  export_classes <- character()
  export_methods <- character()
  imports <- character()
  import_from <- list() # pkg -> character vector of names
  use_dyn_lib <- character()

  for (b in blocks) {
    if (tag_present(b$tags, "export")) {
      val <- str_trim(tag_value(b$tags, "export"))
      nms <- if (!is.null(val) && nzchar(val)) strsplit(val, "[ \t]+")[[1]] else b$obj_name
      nms <- nms[!is.na(nms) & nzchar(nms)]
      exports <- c(exports, nms)
    }

    if (tag_present(b$tags, "exportS3Method")) {
      parts <- s3_method_parts(tag_value(b$tags, "exportS3Method"), b$obj_name)
      generic <- parts$generic
      class <- parts$class
      if (nzchar(generic) && !is.na(class) && nzchar(class)) {
        s3methods <- c(s3methods, sprintf("S3method(%s, %s)", generic, class))
      }
    }

    for (t in tags_named(b$tags, "exportClass")) {
      val <- str_trim(paste(t$value, collapse = " "))
      nm <- if (nzchar(val)) val else b$obj_name
      export_classes <- c(export_classes, nm)
    }

    for (t in tags_named(b$tags, "exportMethod")) {
      val <- str_trim(paste(t$value, collapse = " "))
      nm <- if (nzchar(val)) val else b$obj_name
      export_methods <- c(export_methods, nm)
    }

    for (t in tags_named(b$tags, "import")) {
      val <- str_trim(paste(t$value, collapse = " "))
      imports <- c(imports, strsplit(val, "[ \t]+")[[1]])
    }

    for (t in tags_named(b$tags, "importFrom")) {
      val <- strsplit(str_trim(paste(t$value, collapse = " ")), "[ \t]+")[[1]]
      pkg <- val[1]
      fns <- val[-1]
      import_from[[pkg]] <- unique(c(import_from[[pkg]], fns))
    }

    for (t in tags_named(b$tags, "useDynLib")) {
      val <- str_trim(paste(t$value, collapse = " "))
      use_dyn_lib <- c(use_dyn_lib, val)
    }
  }

  list(
    exports = sort(unique(exports)),
    s3methods = sort(unique(s3methods)),
    export_classes = sort(unique(export_classes)),
    export_methods = sort(unique(export_methods)),
    imports = sort(unique(imports)),
    import_from = import_from,
    use_dyn_lib = unique(use_dyn_lib)
  )
}

namespace_roclet_write <- function(pkgdir, ns) {
  lines <- "# Generated by tinyroxygen: do not edit by hand"

  for (v in ns$use_dyn_lib) lines <- c(lines, sprintf("useDynLib(%s)", v))
  for (v in ns$s3methods) lines <- c(lines, v)
  for (v in ns$exports) lines <- c(lines, sprintf("export(%s)", v))
  for (v in ns$export_classes) lines <- c(lines, sprintf("exportClasses(%s)", v))
  for (v in ns$export_methods) lines <- c(lines, sprintf("exportMethods(%s)", v))
  for (v in ns$imports) lines <- c(lines, sprintf("import(%s)", v))
  for (pkg in sort(names(ns$import_from))) {
    fns <- sort(ns$import_from[[pkg]])
    lines <- c(lines, sprintf("importFrom(%s,%s)", pkg, paste(fns, collapse = ",")))
  }

  writeLines(lines, file.path(pkgdir, "NAMESPACE"))
  invisible(lines)
}
