plot_ensemble_mean <- function(recipe, fcst, outdir) {

  ## TODO: Add 'anomaly' to plot title
  # Abort if frequency is daily
  if (recipe$Analysis$Variables$freq == "daily_mean") {
    stop("Visualization functions not yet implemented for daily data.")
  }

  latitude <- fcst$coords$lat
  longitude <- fcst$coords$lon
  archive <- get_archive(recipe)
  system_name <- archive$System[[recipe$Analysis$Datasets$System$name]]$name
  start_date <- paste0(recipe$Analysis$Time$fcst_year,
                       recipe$Analysis$Time$sdate)
  init_month <- as.numeric(substr(recipe$Analysis$Time$sdate,
                                  start = 1, stop = 2))
  if (!is.null(recipe$Analysis$Workflow$Visualization$projection)) {
    projection <- tolower(recipe$Analysis$Workflow$Visualization$projection)
  } else {
    projection <- "cylindrical_equidistant"
  }

  # Compute ensemble mean
  ensemble_mean <- s2dv::MeanDims(fcst$data, 'ensemble')
  # Loop over variable dimension
  for (var in 1:fcst$dims[['var']]) {
    variable <- fcst$attrs$Variable$varName[[var]]
    var_long_name <- fcst$attrs$Variable$metadata[[variable]]$long_name
    units <- fcst$attrs$Variable$metadata[[variable]]$units
    # Subset ensemble mean by variable
    var_ens_mean <- ClimProjDiags::Subset(ensemble_mean,
                                          along = c("dat", "var",
                                                    "sday", "sweek"),
                                          indices = list(1, var, 1, 1),
                                          drop = 'selected')

    var_ens_mean <- Reorder(var_ens_mean, c("syear",
                                            "time",
                                            "longitude",
                                            "latitude"))
    ## TODO: Redefine column colors, possibly depending on variable
    if (variable == 'prlr') {
      palette = "BrBG"
      rev = F
    } else {
      palette = "RdBu"
      rev = T
    }
    # Define brks, centered around zero in the case of anomalies
    if (grepl("anomaly", var_long_name)) {
      variable <- paste(variable, "anomaly")
      max_value <- max(abs(var_ens_mean))
      ugly_intervals <- seq(-max_value, max_value, max_value/20)
      brks <- pretty(ugly_intervals, n = 12, min.n = 8)
    } else {
      brks <- pretty(range(var_ens_mean, na.rm = T), n = 15, min.n = 8)
    }
    cols <- grDevices::hcl.colors(length(brks) - 1, palette, rev = rev)

    for (i_syear in start_date) {
      if (length(start_date) == 1) {
        i_var_ens_mean <- var_ens_mean[which(start_date == i_syear), , , ]
        outfile <- paste0(outdir[[var]], "forecast_ensemble_mean-", start_date)
      } else {
        i_var_ens_mean <- var_ens_mean[which(start_date == i_syear), , , ]
        outfile <- paste0(outdir[[var]], "forecast_ensemble_mean-", i_syear)
      }
      toptitle <- paste0(system_name, " / ", str_to_title(var_long_name),
                         "\n", "Forecast Ensemble Mean / ", "Init.: ", i_syear)
      months <- lubridate::month(fcst$attrs$Dates[1, 1, which(start_date == i_syear), ],
                                 label = T, abb = F)

      if (recipe$Analysis$Workflow$Visualization$multi_panel) { 
        # Define name of output file and titles
        titles <- as.vector(months)
        # Plots
        PlotLayout(PlotEquiMap, c('longitude', 'latitude'),
                   i_var_ens_mean, longitude, latitude,
                   filled.continents = F,
                   toptitle = toptitle,
                   title_scale = 0.7,
                   subtitle_scale = 0.8,
                   subtitle_margin_scale = 2,
                   titles = titles,
                   units = units,
                   cols = cols,
                   brks = brks,
                   fileout = paste0(outfile, ".png"),
                   bar_label_digits = 4,
                   extra_margin = rep(1, 4),
                   bar_label_scale = 1.5,
                   axes_label_scale = 1.1)
      } else {
        # Define function and parameters depending on projection
        if (projection == 'cylindrical_equidistant') {
          fun <- PlotEquiMap
          base_args <- list(var = NULL, dots = NULL,
                            lon = longitude, lat = latitude,
                            dot_symbol = 20, title_scale = 0.6,
                            filled.continents = F, brks = brks, cols = cols,
                            bar_label_digits = 4, bar_label_scale = 1.5,
                            axes_label_scale = 1)
        } else {
          fun <- PlotRobinson
          common_projections <- c("robinson", "stereographic", "lambert_europe")
          if (projection %in% common_projections) {
            target_proj <- get_proj_code(projection)
          } else {
            target_proj <- projection
          }
          base_args <- list(data = NULL, mask = NULL,
                            lon = longitude, lat = latitude,
                            lon_dim = 'longitude', lat_dim = 'latitude',
                            target_proj = target_proj, legend = 's2dv',
                            style = 'point', brks = brks, cols = cols)
        }
        # Loop over forecast times
        for (i in 1:length(months)) {
          # Get forecast time label
          forecast_time <- match(months[i], month.name) - init_month + 1
          if (forecast_time < 1) {
            forecast_time <- forecast_time + 12
          }
          forecast_time <- sprintf("%02d", forecast_time)
          # Define plot title
          toptitle <- paste(system_name, "/",
                            str_to_title(var_long_name),
                            "\n", "Forecast Ensemble Mean /", months[i])
          # Define caption
          if (identical(fun, PlotRobinson)) {
            ## TODO: Customize technical details
            base_args[['caption']] <-
              paste0("Nominal start date: ", start_date, "\n",
                     "Forecast month: ", sprintf("%02d", i), "\n",
                     "Reference: ", recipe$Analysis$Datasets$Reference)
          }
          # Modify base arguments
          base_args[[1]] <- i_var_ens_mean[i, , ]
          fileout <- paste0(outfile, "_ft", sprintf("%02d", i), ".png")
          # Plot
          do.call(fun,
                  args = c(base_args,
                           list(toptitle = toptitle,
                                fileout = fileout)))
        }
      }
    }
  }
  info(recipe$Run$logger,
       "##### SKILL METRIC PLOTS SAVED TO OUTPUT DIRECTORY #####")
}
