#' Scorecards load metrics from verification suite
#' 
#'@description Scorecards function to load saved data files 
#'
#'@param system A vector of character strings defining the names of the 
#'  system names following the archive.yml format from verification suite. 
#'  Accepted system names: 'ECMWF-SEAS5', 'DWD-GFCS2.1', 'CMCC-SPS3.5',
#'  'ecmwfs5','Meteo-France-System 7', 'UK-MetOffice-GloSea600', 'NCEP-CFSv2'.
#'@param reference A vector of character strings defining the names of 
#'  the references following the archive.yml format from verification suite 
#'  Pending to be test with more than one. The accepted names are: 'era5'.
#'@param var A character string following the format from 
#'  variable-dictionary.yml from verification suite (TO DO: multiple variables). 
#'  The accepted names are: 'psl', 'tas', 'sfcWind', 'prlr'.
#'@param start.year A numeric indicating the start year of the reference period
#'@param end.year A numeric indicating the end year of the reference period
#'@param start.months A vector indicating the numbers of the start months
#'@param forecast.months A vector indicating the numbers of the forecast months
#'@param input.path A character string indicating the path where metrics output 
#'  files from verification suite are saved (or any other compatible files)
#'
#'@return A is a list by system and reference containing an array of with 
#'   the following dimensions: longitude, latitude, forecast months, metrics, 
#'   start dates.

#'@examples
#'\dontrun{
#'loaded_metrics <- LoadMetrics(system = c('ECMWF-SEAS5','DWD-GFCS2.1'),
#'                              reference. = 'ERA5',
#'                              var = 'tas',
#'                              start.year = 1993,
#'                              end.year = 2016,
#'                              metrics =  c('mean_bias', 'enscorr', 'rpss', 'crpss', 'enssprerr'),
#'                              start.months = sprintf("%02d", 1:12),
#'                              forecast.months = 1:6,
#'                              input.path = '/esarchive/scratch/nmilders/scorecards_data/input_data')
#'}
#'@import easyNCDF
#'@import multiApply
#'@export 
LoadMetrics <- function(system, reference, var, start.year, end.year,
                        metrics, start.months, forecast.months,
                        inf_to_na = FALSE,
                        input.path) {
  
  # Initial checks
  ## system
  if (!is.character(system)) {
    stop("Parameter 'system' must be a character vector with the system names.")
  }
  ## reference
  if (!is.character(reference)) {
    stop("Parameter 'reference' must be a character vector with the reference ",
         "names.")
  }
  ## var
  if (!is.character(var)) {
    stop("Parameter 'var' must be a character vector with the var ",
         "names.")
  }
  if (length(var) > 1) {
    warning("Parameter 'var' must be of length one. Only the first value ", 
            "will be used.")
    var <- var[1]
  }
  ## start.year
  if (!is.numeric(start.year)) {
    stop("Parameter 'start.year' must be a numeric value.")
  }
  ## end.year
  if (!is.numeric(end.year)) {
    stop("Parameter 'end.year' must be a numeric value.")
  }
  ## metrics
  if (!is.character(metrics)) {
    stop("Parameter 'metrics' cannot be NULL.")
  }
  ## start.months
  if (is.character(start.months)) {
    warning("Parameter 'start.months' must be a numeric vector indicating ", 
            "the starting months.")
    start.months <- as.numeric(start.months)
  }
  if (!is.numeric(start.months)) {
    stop("Parameter 'start.months' must be a numeric vector indicating ", 
         "the starting months.")
  }
  start.months <- sprintf("%02d", start.months)
  ## Check if sdates are continuous or discrete
  if (all(diff(as.numeric(start.months)) == 1)) {
    consecutive_start.months <- TRUE
  } else {
    consecutive_start.months <- FALSE
  }
  ## forecast.months
  if (!is.numeric(forecast.months)) {
    stop("Parameter 'forecast.months' must be a numeric vector indicating ", 
         "the starting months.")
  }
  ## input.path 
  if (!is.character(input.path)) {
    stop("Parameter 'input.path must be a character string.")
  }
  if (length(input.path) > 1) {
    input.path <- input.path[1]
    warning("Parameter 'input.path' has length greater than 1 and only the ",
            "first element will be used.")
  }
  
  ## Remove . from names
  system <- gsub('.','', system, fixed = T)
  reference <- gsub('.','', reference, fixed = T)
  
  period <- paste0(start.year, "-", end.year)
  
  ## Define empty list to saved data
  all_metrics <- sapply(system, function(x) NULL)
  names(all_metrics) <- system
  ## Load data for each system
  for (sys in 1:length(system)) {
    ## Define empty list to saved data
    by_reference <- sapply(reference, function(x) NULL)
    names(by_reference) <- reference
    ## Load data for each reference
    for (ref in 1:length(reference)) {
      ## Call function to load metrics data
      met <- .Loadmetrics(input.path = input.path, # recipe$Run$output, 
                          system = system[sys],
                          reference = reference[ref],
                          var = var,
                          period = period, 
                          start.months = start.months,
                          forecast.months = forecast.months,
                          metrics = metrics)
      ## Save metric data as array in reference list
      by_reference[[reference[ref]]] <- met
      ## Remove -Inf from crpss data if variable is precipitation
      if (inf_to_na) {
        by_reference[[reference]][by_reference[[reference]]==-Inf] <- NA      
      }
    } ## close loop on reference
    ## Save reference data in list of system
    all_metrics[[system[sys]]] <- by_reference
  } ## close loop on system
  
  return(all_metrics)
} ## close function

############################################################

.Loadmetrics <- function(input.path, system, reference, 
                         var, period, start.months, 
                         forecast.months, metrics) {
  
  ## Load data for each start date
  allfiles <- sapply(start.months, function(m) {
    paste0(input.path, "/", system, "/", var, 
           "/scorecards_", system, "_", reference, "_", 
           var, "-skill_", period, "_s", m, # mod.pressure,
           ".nc")})
  allfiles_exist <- sapply(allfiles, file.exists)
  # Check dims
  files_exist_by_month <- seq(1:length(allfiles))[allfiles_exist]
  allfiledims <- sapply(allfiles[allfiles_exist], easyNCDF::NcReadDims)
  if (length(files_exist_by_month) == 0) {
    stop("No files are found.")
  }
  
  num_dims <- numeric(dim(allfiledims)[1])
  for (i in 1:dim(allfiledims)[1]) {
    if (length(unique(allfiledims[i,])) > 1) {
      warning(paste0("Dimensions of system ", system," with var ", var, 
                     " don't match."))
    }
    num_dims[i] <- max(allfiledims[i,]) # We take the largest dimension
  }
  # dims: [metric, longitude, latitude, time, smonth]
  # or [metric, region, time, smonth] 
  
  # Loop for file
  dim(allfiles) <- c(dat = 1, sdate = length(allfiles))
  
  array_met_by_sdate <- Apply(data = allfiles, target_dims = 'dat', fun = function(x) {
    if (file.exists(x)) {
      res <- easyNCDF::NcToArray(x, vars_to_read = metrics, unlist = T,
                                 drop_var_dim = T)
      names(dim(res)) <- NULL
    } else {
      res <- array(dim = c(length(metrics), allfiledims[-1,1]))
      names(dim(res)) <- NULL
    }
    res})$output1
  
  dim(array_met_by_sdate) <- c(metric = length(metrics), allfiledims[-1,1], 
                               sdate = length(allfiles))
  
  # Attributes
  # Read attributes from the first existing file
  if ("region" %in% rownames(allfiledims)) {
    file_for_att <- ncdf4::nc_open(allfiles[allfiles_exist[1]])
    region <- ncdf4::ncatt_get(file_for_att, 'region')
    ncdf4::nc_close(file_for_att)                  
    attributes(array_met_by_sdate)$region <- region
  } else {
    lon <- easyNCDF::NcToArray(allfiles[allfiles_exist][1], vars_to_read = 'longitude', 
                               unlist = T, drop_var_dim = T)
    lat <- easyNCDF::NcToArray(allfiles[allfiles_exist][1], vars_to_read = 'latitude', 
                               unlist = T, drop_var_dim = T)
    attributes(array_met_by_sdate)$lon <- lon
    attributes(array_met_by_sdate)$lat <- lat
  }
  attributes(array_met_by_sdate)$metrics <- metrics
  attributes(array_met_by_sdate)$start.months <- start.months
  attributes(array_met_by_sdate)$forecast.months <- forecast.months
  return(array_met_by_sdate)
}
