#' @title Generate provenance for SUNSET command calls
#' @description Generate provenance information for command calls based on metaclipR function metalcipR.graph.Command()
#' @param graph Current provenance graph. 
#' @param package Package name
#' @param version Version name 
#' @param function Function name 
#' @param arg.list Argument list
#' @param origin.node.name List containing the name of the origin nodes to be linked to the command call
#' @return List containing updated graph.
#' @references https://earth.bsc.es/gitlab/es/sunset/-/wikis/home GitLab repository for SUNSET, a modular tool for climate forecast verification workflows.
#' @references This function is based on the semantics outlined in the ontology within the Metaclip Framework (available at \url{http://www.metaclip.org/}).

SunsetProv.Command<-function(graph, package, version, fun, arg.list, origin.node.name){
  #Check the inputs are correctly defined
  if(!is.null(fun)) {
      cmd.node.name <- paste0("Command_", randomName())
      # Argument and ArgumentValue
      if(is.list(arg.list)) {
          graph <- my_add_vertices(graph,  
                                    name = cmd.node.name, 
                                    className = "ds:Command",
                                    label = fun,
                                    attr = list("prov:value" = fun))

          # Add the edge linking the step with the command 
          for (i in 1:length(origin.node.name)) {
              graph <- add_edges(graph, 
                                  c(getNodeIndexbyName(graph, origin.node.name[i]),
                                    getNodeIndexbyName(graph, cmd.node.name)),
                                  label = "ds:hadCommandCall")    
          }
          arg.names <- names(arg.list)
          if (!is.null(arg.names)) {
              for (i in 1:length(arg.list)) {
                  arg.node.name <- paste("Argument", arg.names[i], randomName(), sep = ".")
                  graph <- add_vertices(graph, 1,
                                        name = arg.node.name, 
                                        className = "ds:Argument",
                                        label = arg.names[i],
                                        attr = list("prov:value" = arg.names[i]))
                  graph <- add_edges(graph, 
                                      c(getNodeIndexbyName(graph, cmd.node.name),
                                        getNodeIndexbyName(graph, arg.node.name)),
                                      label = "ds:usedArgument")
                  if (length(arg.list[[i]]) > 0) {
                      for (j in 1:length(arg.list[[i]])) {
                          argval.node.name <- paste0("ArgumentValue.", arg.names[i], ".", j, ".", randomName())
                          arg.val <- if (is.list(arg.list[[i]])) {
                              arg.list[[i]][[j]]
                          } else {
                              arg.list[[i]][j]
                          }
                          if (is.function(arg.val)) {
                              arg.val <- paste(deparse(arg.val), collapse = "")
                              arg.val <- gsub("\"","'", arg.val)
                          }
                          tipo <- as.character(typeof(arg.val))
                          arg.val <- gsub("\n", "-", arg.val)
                          if (is.null(arg.val) | length(arg.val) == 0) arg.val <- "NULL"
                          graph <- add_vertices(graph, 1, name = argval.node.name, 
                                                className = "ds:ArgumentValue",
                                                label = arg.val,
                                                attr = list("prov:value" = arg.val,
                                                            "ds:withDataType" = tipo))
                          graph <- add_edges(graph,
                                              c(getNodeIndexbyName(graph, arg.node.name),
                                                getNodeIndexbyName(graph, argval.node.name)),
                                              label = "ds:hadArgumentValue")
                      }
                  } else {
                      argval.node.name <- paste("ArgumentValue", arg.names[i], randomName(), sep = ".")
                      graph <- add_vertices(graph, 1, name = argval.node.name, 
                                            className = "ds:ArgumentValue",
                                            label = "NULL",
                                            attr = list("prov:value" = "NULL",
                                                        "ds:withDataType" = typeof(arg.list[[i]])))
                      graph <- add_edges(graph,
                                          c(getNodeIndexbyName(graph, arg.node.name),
                                            getNodeIndexbyName(graph, argval.node.name)),
                                          label = "ds:hasArgumentValue")
                  }
              }
          }
      } else if (is.character(arg.list)) {
          if (length(arg.list) > 1) stop("Invalid literal command call definition (should be of length one)")
          arg.list %<>% formatCommandCallString()
          graph <- add_vertices(graph, 1, 
                                name = cmd.node.name, 
                                className = "ds:Command",
                                label = fun,
                                attr = list("prov:value" = fun,
                                            "ds:hadLiteralCommandCall" = arg.list))
      }
      for (i in 1:length(origin.node.name)) {
          graph <- add_edges(graph, 
                              c(getNodeIndexbyName(graph, origin.node.name[i]),
                                getNodeIndexbyName(graph, cmd.node.name)),
                              label = "ds:hadCommandCall")    
      }
  }

  # Package
  pkg.nodename <- paste0("Package",randomName())
  graph <- my_add_vertices(graph = graph,
                            name = pkg.nodename, 
                            className = "ds:Package",
                            label = package)
  graph <- add_edges(graph, 
                      c(getNodeIndexbyName(graph, cmd.node.name),
                        getNodeIndexbyName(graph, pkg.nodename)),
                      label = "ds:fromPackage")
  return(graph)                   
}