#' @title Directed metadata graph construction for SUNSET's loaded Dataset.
#' @description Generate provenance for the loaded Dataset within a
#'              SUNSET workflow.
#' @param recipe Configuration file specifying parameters.
#' @param data s2dv_cube object generated by SUNSET's Loading.R function.
#' @param type Type of data: "fcst" for forecast, "hcst" for hindcast,
#'             or "obs" for observational data.
#' @details This function constructs provenance information for the
#'          loaded Dataset within a SUNSET workflow.It creates nodes and
#'          edges representing various aspects of the Dataset, including
#'          its subclass, data provider, modeling center, and project
#'          information.
#' @references This function is based on the semantics outlined
#'             in the Datasource ontology within the Metaclip Framework
#'             (available at \url{http://www.metaclip.org/}).
#' @references https://earth.bsc.es/gitlab/es/sunset/-/tree/Dev-Provenance?ref_type=heads 
#'             Documentation for SUNSET's provenance generation. # nolint: line_length_linter.
#' @import igraph

prov_dataset <- function(recipe, data, type) {
  #First metadata definitions
  horizon <- tolower(recipe$Analysis$Horizon) #'subseasonal','seasonal','decadal'
  exp.name <- recipe$Analysis$Datasets$System$name #System name
  ref.name <- recipe$Analysis$Datasets$Reference$name #Reference name

  #---Dataset setting (extract metadata from conf/ file)
  #Returns a list with the system archive and the reference archive
  archive <- get_archive(recipe)

  #Select the system within the conf file
  exp_descrip <- archive$System[[exp.name]]

  #Select the reference within the conf file
  reference_descrip <- archive$Reference[[ref.name]]

  #Set vocabulary Classes
  args.subclass <- NULL
  modelling.center <- NULL
  dataset.subclass <- 'Dataset'
  if (type == "fcst" || type == "hcst") {
    if (type == "fcst" && horizon == "seasonal") {
      dataset.subclass <- "SeasonalOperationalForecast"
      args.subclass <- "Seasonal Forecast"
    }else if (type == "hcst" && horizon == "seasonal") {
      dataset.subclass <- "SeasonalHindcast"
      args.subclass <- "Seasonal Hindcast"
    }else if (horizon == "decadal" && type == "fcst") {
      args.subclass <- "Forecast decadal simulation, focused on predicting 
        long-term climate patterns and variability over a 10-year period."
    }else if (horizon == "decadal" && type == "hcst") {
      args.subclass <- "Hindcast decadal simulation, aimed at reconstructing 
        historical climate data for the past 10 years to validate 
        model accuracy."
    }else if (horizon == "subseasonal" && type == "fcst") {
      args.subclass <- "Forecast subseasonal simulation, targeting short-term 
        climate predictions over a few weeks to a few months."
    }else if (horizon == "subseasonal" && type == "hcst") {
      args.subclass <- "Hindcast subseasonal simulation, reconstructing past 
        weather patterns on a weeks-to-months timescale to improve 
          model forecasts."
    }
    modelling.center <- exp_descrip$modelling_center
    fullname <- exp_descrip$institution

    if (!is.null(modelling.center)) {
      if (modelling.center == "ECMWF") {
        modelling.center.nodename <- "ds:ECMWF"
        modelling.center <- "ECMWF"
      }else {
        modelling.center.nodename <- "ModellingCenter"
      }
    }
  }else if (type == "obs") {
    dataset.subclass <- "ObservationalDataset"
    modelling.center <- reference_descrip$modelling_center
    fullname <- reference_descrip$institution

    if (!is.null(modelling.center)) {
      #These are individuals defined in the METACLIP datasource ontology
      if (modelling.center == "ERA5" || modelling.center == "ERA5-Land") {
        dataset.subclass <- "Reanalysis"
        modelling.center.nodename <- "ds:ERA5"
        modelling.center <- "ERA5"
      }else if (modelling.center == "ECMWF") {
        modelling.center.nodename <- "ds:ECMWF"
        modelling.center <- "ECMWF"
      }else {
        modelling.center.nodename <- paste0("ModellingCenter_", type)
      }
    }
  }

  # Terms to be included in METACLIP
    #-DecadalForecast
    #-DecadalHindcast
    #-SubseasonalForecast
    #-SubseasonalHindcast

  #Create the main graph
  graph <- make_empty_graph(0)
  members <- length(data[[type]]$coords$ensemble)

  #Add Dataset node
  dataset.nodename <- paste0("Dataset_", type)
  graph <- add_vertices_sunset(graph,
                               nv = 1,
                               name = dataset.nodename,
                               label = "Dataset",
                               className = paste0("ds:", dataset.subclass),
                               attr = list("dc:description" = args.subclass,
                                           "ds:hadMember" = members))

  #Add Data Provider
  #data.provider <- "CDS"
  #data.provider.nodename <- "ds:CDS"
  #graph <- add_vertices(graph,
  #                      nv = 1,
  #                      name = data.provider.nodename,
  #                      label = data.provider,
  #                      className = "ds:DataProvider")
  #graph <- add_edges(graph,
  #                   c(getNodeIndexbyName(graph, dataset.nodename),
  #                     getNodeIndexbyName(graph, dataProvider.nodename)),
  #                   label = "ds:hadDataProvider")

  #Add Modelling Center
  if (!is.null(modelling.center)) {
    graph <- add_vertices_sunset(graph,
                                 nv = 1,
                                 name = modelling.center.nodename,
                                 label = modelling.center,
                                 className = "ds:ModellingCenter",
                                 attr = list("dc:title" = fullname))

    graph <- add_edges(graph,
                       c(getNodeIndexbyName(graph, dataset.nodename),
                         getNodeIndexbyName(graph, modelling.center.nodename)),
                       label = "ds:hadModellingCenter")
  }

  #Add Project
  #Project.nodename <- paste0("Project_", type)
  #graph <- add_vertices(graph,
  #                      nv = 1,
  #                      name = "ds:Copernicus",
  #                      label = "Copernicus",
  #                      className = "ds:Project")

  #graph <- add_edges(graph,
  #                   c(getNodeIndexbyName(graph, dataset.nodename),
  #                     getNodeIndexbyName(graph, "ds:Copernicus")),
  #                   label = "ds:hadProject")

  var_names <- unlist(strsplit(recipe$Analysis$Variables$name,
                               ",\\s*"))
  directory <- list()
  i <- 0

  for (var in var_names) {
    #Add main directory
    i <- i + 1
    directory_nodename <- paste0("Location_", "Dataset_", type, "_",  i)
    if (type == "fcst" || type == "hcst") {
      directory <- paste0(archive$src, exp_descrip$src,
                          exp_descrip[[recipe$Analysis$Variables$freq]]
                          [[var]])
    }else if (type == "obs") {
      directory <- paste0(archive$src, reference_descrip$src_ref,
                          reference_descrip[[recipe$Analysis$Variables$freq]]
                          [[var]])
    }

    graph <- add_vertices(graph,
                          nv = 1,
                          name = directory_nodename,
                          label = directory,
                          className = "prov:Location",
                          attr = list("prov:value" = directory,
                                      "dc:description" = "Barcelona 
                                      Supercommputing Center Earth 
                                      Science Department
                                      local repository. More information 
                                      about the datasets can be found 
                                      in SUNSETs
                                      configuration files.",
                                      "prov:atTime" = as.character(Sys.time())))

    graph <- add_edges(graph,
                       c(getNodeIndexbyName(graph, dataset.nodename),
                         getNodeIndexbyName(graph, directory_nodename)),
                       label = "prov:atLocation")
  }
  return(list("graph" = graph, "parentnodename" = dataset.nodename))
}
