#' Scorecards spatial aggregation of loaded metrics
#' 
#'@description Scorecards function to perform the spatial aggregation of the 
#'  loaded metrics for the specified regions.
#'
#'@param loaded_metrics is a list of arrays containing the metrics loaded by the
#'  function SC_load_metrics.
#'@param region is a named list of vectors containing the desired regions to 
#'  analyze. For each region the following should be specified in this order:
#'  lon_min, lon_max, lat_min, lat_max.
#'@param metric.aggregation a character indicating whether the skill score RPS 
#' and CRPSS are calculated from aggregated scores or aggregated skill score 
#' directly, either 'score' or 'skill' respectively
#'@param ncores is the number of cores to use for the calculation.
#'
#'@return An array with the following dimensions: system, reference, metrics, 
#' time, sdate, region.
#' 
#'@examples
#'regions <- list('global' = c(lon.min = 0, lon.max = 360, lat.min = -90, lat.max = 90),
#'                'europe' = c(lon.min = -10, lon.max = 40, lat.min = 30, lat.max = 70))
#'aggregated_metrics <- WeightedMetrics(loaded_metrics,
#'                                             regions = regions,
#'                                             metric.aggregation = 'skill',
#'                                             ncores = 4)
#'@import multiApply
#'@importFrom ClimProjDiags WeightedMean
#'@importFrom s2dv Reorder
#'@export
WeightedMetrics <- function(loaded_metrics, regions, metric.aggregation,
                            ncores = NULL, na.rm = TRUE) {
  ## Initial checks
  # loaded_metrics
  if (any(sapply(loaded_metrics, function(x) {
    sapply(x, function(y) {is.null(dim(y))})
  }))) {
    stop(paste0("Parameter 'loaded_metrics' must be a list of lists of arrays ", 
                "with named dimensions."))
  }
  # regions
  if (!all(sapply(regions, is.numeric))) {
    stop(paste0("Parameter 'regions' must be a named list of vectors ", 
                "containing the desired regions to analyze."))
  }
  # metric.aggregation
  if (!is.character(metric.aggregation)) {
    stop("Parameter 'metric.aggregation' must be a character indicating.")
  }
  # ncores
  if (!is.numeric(ncores)) {
    stop("Parameter 'ncores' must be an integer.")
  }
  
  ## Get metric names
  ## TO DO: check all metric are in the same order for all sys
  metrics <- attributes(loaded_metrics[[1]][[1]])$metrics 
  forecast.months <- attributes(loaded_metrics[[1]][[1]])$forecast.months 
  start.months <- attributes(loaded_metrics[[1]][[1]])$start.months 
  
  all_metric_means <- array(dim = c(metric = length(metrics), 
                                    time = length(forecast.months), 
                                    sdate = length(start.months), 
                                    region = length(regions), 
                                    reference = length(loaded_metrics[[1]]),
                                    system = length(loaded_metrics)))
  
  ## Loop over system
  for (sys in 1:length(loaded_metrics)) {
    ## Loop over reference
    for (ref in 1:length(loaded_metrics[[sys]])) {
      dimnames <- names(dim(loaded_metrics[[sys]][[ref]]))
      lon_dim_name <- dimnames[which(dimnames %in% .KnownLonNames())]
      lat_dim_name <- dimnames[which(dimnames %in% .KnownLatNames())]
      ## Get latitude and longitude from attributes of loaded metrics
      ## Loop over region
      for (reg in 1:length(regions)) {
        ## Calculate weighted means for defined regions for each system and reference
        weighted.mean <- WeightedMean(data = loaded_metrics[[sys]][[ref]], 
                                      lon = as.vector(attributes(loaded_metrics[[sys]][[ref]])$lon), 
                                      lat = as.vector(attributes(loaded_metrics[[sys]][[ref]])$lat),
                                      region = regions[[reg]], 
                                      londim = lon_dim_name, 
                                      latdim = lat_dim_name,
                                      na.rm = na.rm, 
                                      ncores = ncores)
        all_metric_means[, , , reg, ref, sys] <- weighted.mean
      } ## close loop on region
    } ## close loop on reference
  } ## close loop on system
  
  ## reorder dimensions in array
  all_metric_means <- s2dv::Reorder(all_metric_means, c('system','reference','metric','time','sdate','region'))
  
  ## Add attributes
  attributes(all_metric_means)$metrics <- metrics
  attributes(all_metric_means)$start.months <- attributes(loaded_metrics[[1]][[1]])$start.months
  attributes(all_metric_means)$forecast.months <- attributes(loaded_metrics[[1]][[1]])$forecast.months
  attributes(all_metric_means)$regions <- regions
  attributes(all_metric_means)$system.name <- names(loaded_metrics)
  attributes(all_metric_means)$reference.name <- names(loaded_metrics[[1]])
  
  return(all_metric_means)
  
} ## close function

