Statistics <- function(recipe, data, agg = 'global') {
  # data$hcst: s2dv_cube containing the hindcast 
  # data$obs: s2dv_cube containing the observations
  # recipe: auto-s2s recipe as provided by read_yaml
  # agg: data aggregation

  time_dim <- 'syear'
  memb_dim <- 'ensemble'
  ncores <- recipe$Analysis$ncores

  ## Calculate ensemble mean
  hcst_ensmean <- MeanDims(data$hcst$data, dims = memb_dim)
  obs_ensmean <- MeanDims(data$obs$data, dims = memb_dim)

  statistics_list <- tolower(recipe$Analysis$Workflow$Statistics$metric)
  statistics <- list()
  
  # Compute statistics in the list
  for (stat in strsplit(statistics_list, ", | |,")[[1]]) {
    if (stat %in% c('cov', 'covariance')) {
    ## Calculate covariance
     covariance <- Apply(data = list(x = obs_ensmean, y = hcst_ensmean), 
                         target_dims = time_dim,
                         fun = function(x,y) {cov(as.vector(x),as.vector(y),
                                                 use = "everything", 
                                                 method = "pearson")})$output1
     covariance <- .drop_dims(covariance)
     statistics[[ stat ]] <- covariance
    } else if (stat %in% c('std', 'standard_deviation')) {
      ## Calculate standard deviation 
      std_hcst <- Apply(data = hcst_ensmean, 
                        target_dims = c(time_dim), 
                        fun = 'sd')$output1
      std_obs <- Apply(data = obs_ensmean, 
                       target_dims = c(time_dim), 
                       fun = 'sd')$output1
      std_hcst <- .drop_dims(std_hcst)
      std_obs <- .drop_dims(std_obs)
      statistics[['std_hcst']] <- std_hcst
      statistics[['std_obs']] <- std_obs
    } else if (stat %in% c('var', 'variance')) {
      ## Calculate variance
      var_hcst <- (Apply(data = hcst_ensmean, 
                         target_dims = c(time_dim), 
                         fun = 'sd')$output1)^2
      var_obs <- (Apply(data = obs_ensmean, 
                        target_dims = c(time_dim), 
                        fun = 'sd')$output1)^2
      var_hcst <- .drop_dims(var_hcst)
      var_obs <- .drop_dims(var_obs)
      statistics[['var_hcst']] <- var_hcst
      statistics[['var_obs']] <- var_obs
    } else if (stat == 'n_eff') {
      ## Calculate degrees of freedom
      n_eff <- s2dv::Eno(data = obs_ensmean,
                         time_dim = time_dim,
                         na.action = na.pass,
                         ncores = ncores)
      n_eff <- .drop_dims(n_eff)
      statistics[['n_eff']] <- n_eff
    } else if (stat == 'spread') {
      C_cov <- stats:::C_cov
      spread <- sqrt(Apply(Apply(data = data$hcst$data,
                                 target_dims = c(memb_dim),
                                 fun = stats::var)$output1,
                     fun = 'mean', target_dims = time_dim)$output1)
      spread <- .drop_dims(spread)
      statistics[['spread']] <- spread
    }
  } ## close on stat
  
  info(recipe$Run$logger, "##### STATISTICS COMPUTATION COMPLETE #####")
  .log_memory_usage(recipe$Run$logger, when = "After statistics computation")
 
   # Save outputs
  if (recipe$Analysis$Workflow$Skill$save != 'none') {
    info(recipe$Run$logger, "##### START SAVING STATISTICS #####")
  }
  recipe$Run$output_dir <- file.path(recipe$Run$output_dir,
                                     "outputs", "Statistics")
  
  if (recipe$Analysis$Workflow$Statistics$save == 'all') {
    # Save all statistics
    save_metrics(recipe = recipe, metrics = statistics,
                 data_cube = data$hcst, agg = agg,
                 module = "statistics")
  }
  # Return results
  return(statistics)
}  

