#
#   This work was created by the National Center for Ecological Analysis and Synthesis.
#
#     Copyright 2014
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
#' A custom Roxygen roclet that adds Redland RDF functions to NAMESPACE file generated by Roxygen.
#' @description The redland package uses the SWIG (Simplified Wrapper and Interface Generator) to
#' create the bindings between the Redland RDF C/C++ libraries and R. SWIG creates a NAMESPACE
#' file that contains the function names for the librdf wrapper that it creates, but as of
#' swig 3.0.2 this NAMESPACE file is incorrect and will also be overwritten by Roxygen when
#' 'roxygenize()' or 'devtools:document()' is called, as the wrapper R code doesn't contain
#' Roxygen export annotations used by Roxygen to build the namespace file.
#' To allow for building a NAMESPACE file from all programs in the redland package, this roclet
#' determines the set of wrapper R functions and adds these to the Roxygen generated NAMESPACE file
#' that contains all names from the native R code in the redland package.
#' @details The following line must be present in the DESCRIPTION file for this roclet to be
#' called automatically when 'roxygen2::roxygenize()' or 'devtools::document()' is called:
#' 
#' Roxygen: list(roclets = c("collate", "rd", "namespace", "mergeNamespace_roclet"))
#' 
#' The 'namespace' roclet must always run before the 'mergeNamespace' roclet.
#' @examples
#' \dontrun{
#' roxygen2::roxygenize()
#' devtools::document()
#' }
#' @import roxygen2
#' @param x a roclet
#' @param ... additional parameters
#' @export
mergeNamespace_roclet <- function(x, ...) {
  roclet("mergeNamespace")
}

#' Roxygen process function for the 'mergeNamespace' roclet
#' @description This function is called by the Roxygen2 roxygenize function.
#' @details This function loads the Redland interface file and tests each loaded function to
#' see if it should be exported via the NAMESPACE file.
#' @param x the currently running roclet
#' @param blocks the documentation blocks
#' @param env the current env
#' @param base_path the top directory of the R package
#' @export
roclet_process.roclet_mergeNamespace <- function(x, blocks, env, base_path) {
  #on.exit(detach(".redland-temp"))
  #attach(NULL, name=".redland-temp")
  tmpEnv <- new.env()
  # Load the Redland wrapper file into a temporary environment. This file has a definition of
  # each redland library function that will be made available to the package.
  filePath <- sprintf("%s/R/redland.R", base_path)
  #source(filePath, as.environment(".redland-temp"))
  source(file=filePath, local=as.environment(tmpEnv))
  # Check each Redland function to see if it has the SWIGfunction attribute set, and if so
  # include this function name in the list of functions to be exported
  #funcList <- ls(as.environment(".redland-temp"))
  funcList <- ls(as.environment(tmpEnv))
  exportFuncList <- list()
  for (functionName in funcList) {
    funcType <- attr(get(functionName), "class")[1]
    if(is.null(funcType)) next
    if (funcType == "SWIGFunction") {
      exportFuncList <- c(exportFuncList, functionName)
      #cat(sprintf("func: %s\n", functionName))
    }
  }
  
  rm(list=ls(tmpEnv), envir=tmpEnv)
  rm(tmpEnv)
  
  return(exportFuncList)
}

#' Roxygen output function that merges a base NAMESPACE file with the Roxygen dynamically created NAMSPACE file
#' @description The 'roclet_output' function handles output of the results from the 'roc_process' function.
#' This function merges the NAMESPACE file created by the 'namespace' roclet with the list of Redland RDF
#' functions determined by the 'roc_process' function.
#' @param x the currently running roclet
#' @param results the list of items to process that was generated by the roc_process.mergedNamespace function
#' @param base_path the base directory path of the package
#' @param ... additional parameters
#' @export
roclet_output.roclet_mergeNamespace <- function(x, results, base_path, ...) {

  # Get contents of the NAMESPACE file that was created by the "namespace" roclet
  filePathNS <- file.path(base_path, "NAMESPACE")
  NScontents <- if (file.exists(filePathNS)) readLines(filePathNS) else ""
  
  # Merge the contents of the "namespace" roclet NAMESPACE file with the list
  # of functions from Redland
  mergedContents <- NScontents
  for (tm in results) {
    tm <- sprintf("export(%s)", tm)
    mergedContents <- c(mergedContents, tm)
  }
    
  if (identical(mergedContents, NScontents)) {
    warning("No functions added from Redland wrapper file.")
  } else {
    cat("Adding namespace directives for Redland library\n")
    writeLines(mergedContents, filePathNS)
  }
  
  filePathNS
}

#' @export
roclet_tags.roclet_mergeNamespace <- function(x) {
  list()
}
