#'Function to create all multi system/reference scorecards
#' 
#'@description Scorecards function to create scorecard tables for multiple systems
#' and references (types 9 to 12).
#'@param input_data is an array of spatially aggregated metrics containing the
#'   following dimensions; system, reference, metric, time, sdate, region.
#'@param system a vector of character strings defining the systems following the
#'   archive.yml format for SUNSET.
#'@param reference a vector of character strings defining the references 
#'  following the archive.yml format for SUNSET.
#'@param var a character string indicating the variable.
#'@param var.units a character sting indicating the the variable units.
#'@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.date a vector of character strings indicating the start months
#'@param forecast.month a vector of numeric indicating the forecast months
#'@param region.names a vector of character strings containing names of the 
#'  regions corresponding to the input data
#'@param metrics a vector of character strings containing the metrics.
#'@param table.label a character string containing additional information to 
#'  include in the scorecard title
#'@param fileout.label a character string containing additional information to 
#'  include in the output png file when saving the scorecard.
#'@param plot.legend A logical value to determine if the legend is plotted.
#'@param legend.white.space A numeric value defining the initial starting 
#'  position of the legend bars, the white space infront of the legend is 
#'  calculated from the left most point of the table as a distance in cm.
#'@param legend.width A numeric value to define the width of the legend bars.
#'@param legend.height A numeric value to define the height of the legend bars.
#'@param label.scale A numeric value to define the size of the legend labels.
#'@param col1.width A numeric value defining the width of the first table column
#'  in cm.
#'@param col2.width A numeric value defining the width of the second table 
#'  column in cm.
#'@param columns.width A numeric value defining the width all columns within the 
#'  table in cm (excluding the first and second columns containing the titles).
#'@param font.size A numeric indicating the font size on the scorecard table.
#'@param round.decimal A numeric indicating to which decimal point the data 
#'  is to be displayed in the scorecard table. Default is 2.
#'@param output.path a path of the location to save the scorecard plots.
#'
#'@return
#' This function returns 4 scorecard images for each region requested, the 
#' images are saved in the directory output.path.

#'@example
#' scorecard_diff <- ScorecardsDiff(data = aggregated_metrics,
#'                                    system.name = c('ECMWF-SEAS5','DWD-GFCS2.1'),
#'                                    reference.name = 'ERA5',
#'                                    var = 'tas', 
#'                                    var.units = 'C',
#'                                    start.year = 1993,
#'                                    end.year = 2016,
#'                                    start.months = 1:12,
#'                                    forecast.months = 1:6,
#'                                    region.names = c('Tropics', 'Extra-tropical NH', 'Extra-tropical SH')
#'                                    metrics = c('mean_bias', 'enscorr', 'rpss','crpss', 'enssprerr'),
#'                                    table.label = '(Interpolation = to system, Aggregation level = skill, Cross-validation = terciles)',
#'                                    fileout.label = '_crossval-terciles_agg-skill',
#'                                    output.path = '/esarchive/scratch/nmilders/scorecards_images/testing'
#'                                    )


ScorecardsSystemDiff <- function(data, system, reference, var, var.units,
                                 start.year, end.year, start.months, forecast.months, 
                                 region.names, metrics, plot.legend = TRUE, 
                                 # legend.breaks = NULL, 
                                 legend.white.space = NULL, 
                                 legend.width = 550, legend.height = 50,
                                 table.label = NULL, fileout.label =  NULL,
                                 label.scale =  1.4, font.size = 1.1, 
                                 col1.width = NULL, col2.width = NULL, 
                                 columns.width = 1.2,
                                 round.decimal = 2, output.path){

  ## Initial checks
  # data
  if (!is.array(data)) {
    stop("Parameter 'data' must be an array with named dimensions.")
  }
  if (!is.array(data)) {
    stop("Parameter 'data' must be an array with named dimensions.")
  }
  if (is.null(names(dim(data)))) {
    stop("Parameter 'data' must have dimenision names.")
  }
  if (!all(c('system','reference','metric','time','sdate','region') %in% 
           names(dim(data)))) {
    stop("Dimension names of 'data' must be: 'system','reference','metric', 
          'time','sdate','region'.")
  }
  if (is.null(table.label)){
    table.label <- ""
  }
  if (is.null(fileout.label)){
    fileout.label <- ""
  }
  
  ## Make sure input_data is in correct order for using in functions:
  data_order <- c('system','reference','metric','time','sdate','region')
  data <- Reorder(data, data_order)
  
  ## Identify metrics loaded
  metrics_loaded <-  attributes(data)$metrics
  
  ## Select only the metrics to visualize from data
  input_data <- Subset(data, along = 'metric', indices = match(metrics, metrics_loaded))
  attributes(input_data)$metrics <- metrics
  
  ## Calculate difference between two systems/references
  if(length(system) == 2 && length(reference) == 1){
    dataset1 <- Subset(input_data, c('system', 'reference'), list(1, 1), drop = 'selected')
    dataset2 <- Subset(input_data, c('system', 'reference'), list(2, 1), drop = 'selected')
  }
  else if(length(system) == 1 && length(reference) == 2){
    dataset1 <- Subset(input_data, c('system', 'reference'), list(1, 1), drop = 'selected')
    dataset2 <- Subset(input_data, c('system', 'reference'), list(1, 2), drop = 'selected')
  }
  
  ## Calculate difference of mean_bias from 0 for each dataset
  if ('mean_bias' %in% metrics){
    pos_bias <- which(metrics == 'mean_bias')
    dataset1[pos_bias,,,] <- abs(dataset1[pos_bias,,,])
    dataset2[pos_bias,,,] <- abs(dataset2[pos_bias,,,])
  }
  
  ## Calculate difference of enssprerr from 1 for each dataset
  if ('enssprerr' %in% metrics){
    pos_enssprerr <- which(metrics == 'enssprerr')
    dataset1[pos_enssprerr,,,] <- abs(1-dataset1[pos_enssprerr,,,])
    dataset2[pos_enssprerr,,,] <- abs(1-dataset2[pos_enssprerr,,,])
  }
  
  diff_data <- dataset1 - dataset2
  
  # Transform data for scorecards by forecast month (types 3 & 4)
  transformed_data <- SCTransform(data = diff_data,
                                  sdate_dim = 'sdate',
                                  ftime_dim = 'time')
  
  ## Load configuration files
  sys_dict <- read_yaml("conf/archive.yml")[[recipe$Run$filesystem]]
  var_dict <- read_yaml("conf/variable-dictionary.yml")$vars

  ## Get scorecards table display names from configuration files
  var.name <- var_dict[[var]]$long_name
 
  if (is.null(var.units)) {
    var.units <- var_dict[[var]]$units
  }

  system.name <-  NULL
  reference.name <- NULL
  
  for(sys in 1:length(system)){
    system.name1 <- sys_dict$System[[system[sys]]]$name 
    system.name <- c(system.name, system.name1)
  }
  for(ref in 1:length(reference)){
    reference.name1 <- sys_dict$Reference[[reference[ref]]]$name
    reference.name <- c(reference.name, reference.name1)
  }
  
  ## Get metric long names
  metric.names.list <- .met_names(metrics, var.units)
  
  ## format the metric names as character instead of list
  for(met in metrics){
    if(met == metrics[1]){
      metric.names <- metric.names.list[[met]] 
    } else {
      metric.names <- c(metric.names, metric.names.list[[met]])
    }
  }
  
  ## Define parameters depending on system compariosn or reference comparison
  if(length(system) > 1 && length(reference) == 1){
    comparison <- system
    model <- 'system'
    table.model.name <- 'System'
    model.name <- system.name
    eval.label <- 'Ref'
    eval.name <- reference.name
    eval.filename <- reference
  } else if(length(system) == 1 && length(reference) > 1){
    comparison <- reference
    model <- 'reference'
    table.model.name <- 'Reference'
    model.name <- reference.name
    eval.label <- 'Sys'
    eval.name <- system.name
    eval.filename <- system
  } else {stop('Not multi system or multi reference')}
  
  ## Define table colors 
  palette <- c('#2D004B', '#542789', '#8073AC', '#B2ABD2', '#D8DAEB', '#FEE0B6', '#FDB863', '#E08214', '#B35806', '#7F3B08')
  colorunder <- "#04040E"
  colorsup <- "#730C04"

  ## Define breaks for each metric based of metric position:
  legend.breaks <- c(-0.5, -0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5)
  
  ## Define scorecard titles
  table.title <- paste0(var.name, " - Difference: ", model.name[1], " - ", model.name[2], "  ",table.label)
  table.subtitle <- paste0("(", eval.label, ": ", eval.name, " ", start.year, "-", end.year, ")")
  
    #### Scorecard_type 1 ####
    ## (no transformation or reorder)
  
    fileout <- .Filename(system = paste0("diff_",comparison[1],"_",comparison[2]), reference = eval.filename, var = var,
                         start.year = start.year, end.year = end.year, scorecard.type = 1,
                         fileout.label = fileout.label, output.path = output.path)
     VizScorecard(data = diff_data,
                  sign = NULL,
                  row_dim = 'region',
                  subrow_dim = 'time',
                  col_dim = 'metric',
                  subcol_dim = 'sdate',
                  legend_dim = 'metric',
                  row_names = region.names,
                  subrow_names = forecast.months,
                  col_names = metric.names,
                  subcol_names = month.abb[as.numeric(start.months)],
                  table_title = table.title,
                  table_subtitle = table.subtitle,
                  row_title = 'Region',
                  subrow_title = 'Forecast Month',
                  col_title = 'Start date',
                  legend_breaks = legend.breaks,
                  plot_legend = plot.legend,
                  label_scale = label.scale,
                  legend_width = legend.width,
                  legend_height = legend.height,
                  palette = palette,
                  colorunder = colorunder,
                  colorsup = colorsup,
                  round_decimal = round.decimal,
                  font_size = font.size,
                  legend_white_space = legend.white.space, 
                  col1_width = col1.width,
                  col2_width = col2.width,
                  columns_width = columns.width,
                  fileout = fileout)
 
    
    #### Scorecard_type 2 ####
    ## (reorder only)
    ## Scorecard type 2 is same as type 1 for only one region, therefore is
    ## only plotted if more that one region is requested
    if(dim(input_data)['region'] > 1) {
      fileout <- .Filename(system = paste0("diff_",comparison[1],"_",comparison[2]), reference = eval.filename, var = var,
                           start.year = start.year, end.year = end.year, scorecard.type = 2,
                           fileout.label = fileout.label, output.path = output.path)
      new_order <- c('metric', 'region', 'sdate', 'time')
      data_sc_2 <- Reorder(diff_data, new_order)
       VizScorecard(data = data_sc_2,
                    sign = NULL,
                    row_dim = 'time',
                    subrow_dim = 'region',
                    col_dim = 'metric',
                    subcol_dim = 'sdate',
                    legend_dim = 'metric',
                    row_names = forecast.months,
                    subrow_names = region.names,
                    col_names = metric.names,
                    subcol_names = month.abb[as.numeric(start.months)],
                    table_title = table.title,
                    table_subtitle = table.subtitle,
                    row_title = 'Forecast Month',
                    subrow_title = 'Region',
                    col_title = 'Start date',
                    legend_breaks = legend.breaks,
                    plot_legend = plot.legend,
                    label_scale = label.scale,
                    legend_width = legend.width,
                    legend_height = legend.height,
                    palette = palette,
                    colorunder = colorunder,
                    colorsup = colorsup,
                    round_decimal = round.decimal,
                    font_size = font.size,
                    legend_white_space = legend.white.space, 
                    col1_width = col1.width,
                    col2_width = col2.width,
                    columns_width = columns.width,
                    fileout = fileout)
    } ## close if
    
    
    #### Scorecard_type 3 ####
    ## (transformation only)
    fileout <- .Filename(system = paste0("diff_",comparison[1],"_",comparison[2]), reference = eval.filename, var = var,
                         start.year = start.year, end.year = end.year, scorecard.type = 3,
                         fileout.label = fileout.label, output.path = output.path)
     VizScorecard(data = transformed_data,
                  sign = NULL,
                  row_dim = 'region',
                  subrow_dim = 'time',
                  col_dim = 'metric',
                  subcol_dim = 'sdate',
                  legend_dim = 'metric',
                  row_names = region.names,
                  subrow_names = forecast.months,
                  col_names = metric.names,
                  subcol_names = month.abb[as.numeric(start.months)],
                  table_title = table.title,
                  table_subtitle = table.subtitle,
                  row_title = 'Region',
                  subrow_title = 'Forecast Month',
                  col_title = 'Target month',
                  legend_breaks = legend.breaks,
                  plot_legend = plot.legend,
                  label_scale = label.scale,
                  legend_width = legend.width,
                  legend_height = legend.height,
                  palette = palette,
                  colorunder = colorunder,
                  colorsup = colorsup,
                  round_decimal = round.decimal,
                  font_size = font.size,
                  legend_white_space = legend.white.space, 
                  col1_width = col1.width,
                  col2_width = col2.width,
                  columns_width = columns.width,
                  fileout = fileout)
       
    
    #### Scorecard_type 4 ####
    ## (transformation and reorder)
    ## Scorecard type 4 is same as type 3 for only one region, therefore is
    ## only plotted if more that one region is requested
    if(dim(input_data)['region'] > 1) {
      fileout <- .Filename(system = paste0("diff_",comparison[1],"_",comparison[2]), reference = eval.filename, var = var,
                           start.year = start.year, end.year = end.year, scorecard.type = 4,
                           fileout.label = fileout.label, output.path = output.path)
      new_order <- c('metric', 'region', 'sdate', 'time')
      data_sc_4 <- Reorder(transformed_data, new_order)
      VizScorecard(data = data_sc_4,
                   sign = NULL,
                   row_dim = 'time',
                   subrow_dim = 'region',
                   col_dim = 'metric',
                   subcol_dim = 'sdate',
                   legend_dim = 'metric',
                   row_names = forecast.months,
                   subrow_names = region.names,
                   col_names = metric.names,
                   subcol_names = month.abb[as.numeric(start.months)],
                   table_title = table.title,
                   table_subtitle = table.subtitle,
                   row_title = 'Forecast Month',
                   subrow_title = 'Region',
                   col_title = 'Target month',
                   legend_breaks = legend.breaks,
                   plot_legend = plot.legend,
                   label_scale = label.scale,
                   legend_width = legend.width,
                   legend_height = legend.height,
                   palette = palette,
                   colorunder = colorunder,
                   colorsup = colorsup,
                   round_decimal = round.decimal,
                   font_size = font.size,
                   legend_white_space = legend.white.space, 
                   col1_width = col1.width,
                   col2_width = col2.width,
                   columns_width = columns.width,
                   fileout = fileout)
    } ## close if 
    
print("All system difference scorecard plots created")
  
} ## close function      

