###############################################################################
##################### SCORECARDS MODULE FOR SUNSET SUITE ######################
###############################################################################

##### Load source functions #####
source('modules/Scorecards/R/tmp/LoadMetrics.R')
source('modules/Scorecards/R/tmp/WeightedMetrics.R')
source('modules/Scorecards/R/tmp/Utils.R')
source('modules/Scorecards/R/tmp/SCTransform.R')
source('modules/Scorecards/R/tmp/ScorecardsSingle.R')
source('modules/Scorecards/R/tmp/ScorecardsMulti.R')
source('modules/Scorecards/R/tmp/ScorecardsSystemDiff.R')
source('modules/Scorecards/R/tmp/SCPlotScorecard.R') 


## TODO: Change function name to 'Scorecards'?
## Define function
Scorecards <- function(recipe) {
  
  ## set parameters
  input.path <- paste0(recipe$Run$output_dir, "/outputs/Skill/")
  output.path <- paste0(recipe$Run$output_dir, "/plots/Scorecards/")
  dir.create(output.path, recursive = T, showWarnings = F)
  
  system <- recipe$Analysis$Datasets$System$name
  reference <- recipe$Analysis$Datasets$Reference$name
  var <- recipe$Analysis$Variables$name
  start.year <- as.numeric(recipe$Analysis$Time$hcst_start)
  end.year <- as.numeric(recipe$Analysis$Time$hcst_end)
  forecast.months <- recipe$Analysis$Time$ftime_min : recipe$Analysis$Time$ftime_max
  
  if (recipe$Analysis$Workflow$Scorecards$start_months == 'all') {
    start.months <- 1:12
  } else {
    start.months <- as.numeric(strsplit(recipe$Analysis$Workflow$Scorecards$start_months,
                                        split = ", | |,")[[1]])
  }
  
  regions <- recipe$Analysis$Workflow$Scorecards$regions  
  for (i in names(regions)){regions[[i]] <- unlist(regions[[i]])}
  
  metric.aggregation <- recipe$Analysis$Workflow$Scorecards$metric_aggregation
  metrics.load <- unlist(strsplit(tolower(recipe$Analysis$Workflow$Skill$metric), ", | |,"))
  
  ## Define skill scores in score aggregation has been requested
  
  if(metric.aggregation == 'score'){
    if('rps' %in% metrics.load){
      metrics.load <- c(metrics.load, 'rps_clim') 
    }
    if('crps' %in% metrics.load){
      metrics.load <- c(metrics.load, 'crps_clim') 
    }
  }
  
  metrics.visualize <- unlist(strsplit(tolower(recipe$Analysis$Workflow$Scorecards$metric), ", | |,"))
  
  ## Define skill scores in score aggregation has been requested
  
  if(metric.aggregation == 'score'){
    if('rpss' %in% metrics.visualize){
      metrics.visualize[metrics.visualize == 'rpss'] <- 'rpss_score_aggr'
    }
    if('crpss' %in% metrics.visualize){
      metrics.visualize[metrics.visualize == 'crpss'] <- 'crpss_score_aggr'
    }
  }
  
  inf.to.na <-  recipe$Analysis$Workflow$Scorecards$inf_to_na
  table.label <-  recipe$Analysis$Workflow$Scorecards$table_label
  fileout.label <- recipe$Analysis$Workflow$Scorecards$fileout_label
  legend.white.space <- recipe$Analysis$Workflow$Scorecards$legend_white_space 
  col1.width <- recipe$Analysis$Workflow$Scorecards$col1_width
  col2.width <- recipe$Analysis$Workflow$Scorecards$col2_width
  calculate.diff <- recipe$Analysis$Workflow$Scorecards$calculate_diff
  ncores <- 1 # recipe$Analysis$ncores
  
  ## Load data files
  loaded_metrics <- LoadMetrics(system = system,
                                reference = reference,
                                var = var,
                                start.year = start.year,
                                end.year = end.year,
                                metrics =  metrics.load,
                                start.months = start.months,
                                forecast.months = forecast.months,
                                inf_to_na = inf.to.na,
                                input.path = input.path)
  
  
  if('region' %in% names(dim(loaded_metrics[[1]][[1]]))){
    
    ### Convert loaded metrics to array for allready aggregated data
    metrics.dim <- attributes(loaded_metrics[[1]][[1]])$metrics 
    forecast.months.dim <- attributes(loaded_metrics[[1]][[1]])$forecast.months 
    start.months.dim <- attributes(loaded_metrics[[1]][[1]])$start.months 
    regions.dim <- regions #list('NAO' = c(lon.min = -80, lon.max = 40, lat.min = 20, lat.max = 80))
    
    aggregated_metrics <- array(dim = c(system = length(loaded_metrics),
                                        reference = length(loaded_metrics[[1]]),
                                        metric = length(metrics.dim), 
                                        time = length(forecast.months.dim), 
                                        sdate = length(start.months.dim), 
                                        region = length(regions.dim)))
    
    
    for (sys in 1:length(names(loaded_metrics))){
      for (ref in 1:length(names(loaded_metrics[[sys]]))){
        aggregated_metrics[sys, ref, , , , ] <- s2dv::Reorder(data = loaded_metrics[[sys]][[ref]], order = c('metric','time','sdate','region'))
      }
    }
    
    ## Add attributes
    attributes(aggregated_metrics)$metrics <- metrics.load
    attributes(aggregated_metrics)$start.months <- attributes(loaded_metrics[[1]][[1]])$start.months
    attributes(aggregated_metrics)$forecast.months <- attributes(loaded_metrics[[1]][[1]])$forecast.months
    attributes(aggregated_metrics)$regions <- regions
    attributes(aggregated_metrics)$system.name <- names(loaded_metrics)
    attributes(aggregated_metrics)$reference.name <- names(loaded_metrics[[1]])
    
    
  } else {
    ## Calculate weighted mean of spatial aggregation
    aggregated_metrics <- WeightedMetrics(loaded_metrics,
                                          regions = regions,
                                          metric.aggregation = metric.aggregation,
                                          ncores = ncores)
  }## close if

  ## Create simple scorecard tables 
  ## (one system only)
  ## Metrics input must be in the same order as function SC_spatial_aggregation
  scorecard_single <- ScorecardsSingle(data = aggregated_metrics,
                                       system = system,
                                       reference = reference,
                                       var = var,
                                       start.year = start.year,
                                       end.year = end.year,
                                       start.months = start.months,
                                       forecast.months = forecast.months,
                                       region.names = names(regions),
                                       metrics = metrics.visualize,
                                       table.label =  table.label,
                                       fileout.label = fileout.label,
                                       legend.white.space = legend.white.space, 
                                       col1.width = col1.width,
                                       col2.width = col2.width,
                                       output.path = output.path)
  
  ## Create multi system/reference scorecard tables
  ## (multiple systems with one reference or one system with multiple references)
  ## Metrics input must be in the same order as function SC_spatial_aggregation
  if(length(system) >  1 || length(reference) >  1){
    scorecard_multi <- ScorecardsMulti(data = aggregated_metrics,
                                       system = system,
                                       reference = reference,
                                       var = var,
                                       start.year = start.year,
                                       end.year = end.year,
                                       start.months = start.months,
                                       forecast.months = forecast.months,
                                       region.names = attributes(regions)$names,
                                       metrics = metrics.visualize,
                                       table.label =  table.label,
                                       fileout.label = fileout.label,
                                       output.path = output.path)
  } ## close if
  
  
  if(calculate.diff == TRUE){
    if(length(system) ==  2 || length(reference) ==  2){
      scorecard_diff <- ScorecardsSystemDiff(data = aggregated_metrics,
                                             system = system,
                                             reference = reference,
                                             var = var,
                                             start.year = start.year,
                                             end.year = end.year,
                                             start.months = start.months,
                                             forecast.months = forecast.months,
                                             region.names = attributes(regions)$names,
                                             metrics = metrics.visualize,
                                             table.label = table.label,
                                             fileout.label =  fileout.label,
                                             legend.white.space = legend.white.space, 
                                             col1.width = col1.width,
                                             col2.width = col2.width,
                                             output.path = output.path)
    } else {stop ("Difference scorecard can only be computed with two systems or two references.")}
  } ## close if on calculate.diff
  
}

