###############################################################################
##################### 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/VizScorecard.R') 

## Temporary for new ESviz function
source('modules/Scorecards/R/tmp/ColorBarContinuous.R')
source('modules/Scorecards/R/tmp/ClimPalette.R')
.IsColor <- s2dv:::.IsColor
.FilterUserGraphicArgs <- s2dv:::.FilterUserGraphicArgs

## Define function
Scorecards <- function(recipe) {
  
  ## Parameters for loading data files
  skill.input.path <- paste0(recipe$Run$output_dir, "/outputs/Skill/")
  stats.input.path <- paste0(recipe$Run$output_dir, "/outputs/Statistics/")
  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
  calib.method <- tolower(recipe$Analysis$Workflow$Calibration$method)

  if (recipe$Analysis$Workflow$Scorecards$start_months == 'all' || is.null(recipe$Analysis$Workflow$Scorecards$start_months)) {
    start.months <- as.numeric(substr(recipe$Analysis$Time$sdate, 1,2))
  } else {
    start.months <- as.numeric(strsplit(recipe$Analysis$Workflow$Scorecards$start_months,
                                        split = ", | |,")[[1]])
   if(!any(as.numeric(substr(recipe$Analysis$Time$sdate, 1,2))) %in% start.months){
     error(recipe$Run$logger,"Requested start dates for scorecards must be loaded")
   }
  }
  
  start.months <- sprintf("%02d", start.months)
  period <- paste0(start.year, "-", end.year)
  
  ## Parameters for data aggregation
  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), ", | |,"))
  metrics.visualize <- unlist(strsplit(tolower(recipe$Analysis$Workflow$Scorecards$metric), ", | |,"))
  ncores <- 1 # recipe$Analysis$ncores
  
  if(is.null(recipe$Analysis$Workflow$Scorecards$signif_alpha)){
    alpha <- 0.05
  } else {
    alpha <- recipe$Analysis$Workflow$Scorecards$signif_alpha
  }
  
  if (is.null(recipe$Analysis$Workflow$Scorecards$inf_to_na)){
    inf.to.na <- FALSE
  } else {
    inf.to.na <- recipe$Analysis$Workflow$Scorecards$inf_to_na
  }
  
  if(is.null(recipe$Analysis$remove_NAs)){
    na.rm <- FALSE
  } else {
    na.rm <- recipe$Analysis$remove_NAs 
  }
  
  ## Parameters for scorecard layout
  table.label <-  recipe$Analysis$Workflow$Scorecards$table_label
  fileout.label <- recipe$Analysis$Workflow$Scorecards$fileout_label
  col1.width <- recipe$Analysis$Workflow$Scorecards$col1_width
  col2.width <- recipe$Analysis$Workflow$Scorecards$col2_width
  legend.breaks <- recipe$Analysis$Workflow$Scorecards$legend_breaks
  legend.width <- recipe$Analysis$Workflow$Scorecards$legend_width
  
  if (is.null(recipe$Analysis$Workflow$Scorecards$plot_legend)){
    plot.legend <- TRUE
  } else {
    plot.legend <- recipe$Analysis$Workflow$Scorecards$plot_legend
  }
  
  if(is.null(recipe$Analysis$Workflow$Scorecards$columns_width)){
    columns.width <- 1.2
  } else {
    columns.width <- recipe$Analysis$Workflow$Scorecards$columns_width 
  }
  
  if(is.null(recipe$Analysis$Workflow$Scorecards$legend_white_space)){
    legend.white.space <- 6
  } else {
    legend.white.space <- recipe$Analysis$Workflow$Scorecards$legend_white_space
  }

  if(is.null(recipe$Analysis$Workflow$Scorecards$legend_height)){
    legend.height <- 50
  } else {
    legend.height <- recipe$Analysis$Workflow$Scorecards$legend_height
  }
  
  if(is.null(recipe$Analysis$Workflow$Scorecards$label_scale)){
    label.scale <- 1.4
  } else {
    label.scale <- recipe$Analysis$Workflow$Scorecards$label_scale
  }
  
  if(is.null(recipe$Analysis$Workflow$Scorecards$round_decimal)){
    round.decimal <- 2
  } else {
    round.decimal <- recipe$Analysis$Workflow$Scorecards$round_decimal
  }
  
  if(is.null(recipe$Analysis$Workflow$Scorecards$font_size)){
    font.size <- 1.1
  } else {
    font.size <- recipe$Analysis$Workflow$Scorecards$font_size
  }
  
  ## Define if difference scorecard is to be plotted
  if (is.null(recipe$Analysis$Workflow$Scorecards$calculate_diff)){
    calculate.diff <- FALSE
  } else {
    calculate.diff <- recipe$Analysis$Workflow$Scorecards$calculate_diff
  }
  
  ####### SKILL AGGREGATION #######
  if(metric.aggregation == 'skill'){
  
    ## Load data files
    loaded_metrics <- LoadMetrics(input_path = skill.input.path,
                                  system = system,
                                  reference = reference,
                                  var = var,
                                  metrics =  metrics.visualize,
                                  period = period,
                                  start_months = start.months,
                                  calib_method = calib.method,
                                  inf_to_na = inf.to.na
                                  )

    ## Spatial Aggregation of metrics
    if('region' %in% names(dim(loaded_metrics[[1]][[1]]))){
      
      ### Convert loaded metrics to array for already aggregated data
      metrics.dim <- attributes(loaded_metrics)$metrics 
      forecast.months.dim <- forecast.months 
      start.months.dim <- attributes(loaded_metrics)$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)$start_months
      attributes(aggregated_metrics)$forecast.months <- 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,
                                            forecast.months = forecast.months,
                                            metric.aggregation = metric.aggregation,
                                            ncores = ncores)
    } ## close if on region
    metrics_significance <- NULL
    
  } ## close if on skill
  
  ###### SCORE AGGREGATION ######
  if(metric.aggregation == 'score'){

    lon_dim <- 'longitude'
    lat_dim <- 'latitude'
    time_dim <- 'syear'
    memb_dim <- 'ensemble'

    ## Define arrays to filled with data
    aggregated_metrics <- array(data = NA, 
                               dim = c(system = length(system),
                                       reference = length(reference),
                                       time = length(forecast.months), 
                                       sdate = length(start.months), 
                                       region = length(regions),
                                       metric = length(metrics.visualize)))
    
    metrics_significance <- array(data = NA, 
                            dim = c(system = length(system),
                                    reference = length(reference),
                                    time = length(forecast.months), 
                                    sdate = length(start.months), 
                                    region = length(regions),
                                    metric = length(metrics.visualize)))
    
    ## Load and aggregated data for each metric
    for (sys in 1:length(system)){
      for (ref in 1:length(reference)){
        for (met in metrics.visualize) {   
          
          if(met == 'rpss'){
            ## Load data from saved files
            rps_syear <- .loadmetrics(input_path = skill.input.path, system = system[sys],
                                      reference = reference[ref], var = var, 
                                      period = period, start_months = start.months,
                                      calib_method = calib.method, metric = 'rps_syear')
            
            rps_clim_syear <- .loadmetrics(input_path = skill.input.path, system = system[sys],
                                           reference = reference[ref], var = var, 
                                           period = period, start_months = start.months,
                                           calib_method = calib.method, metric = 'rps_clim_syear')
            
            ## Spatially aggregate data
            rps_syear <- sapply(X = 1:length(regions), 
                                FUN = function(X) {
                                  WeightedMean(data = rps_syear,
                                               region = regions[[X]],
                                               lon = as.vector(attributes(rps_syear)$lon),
                                               lat = as.vector(attributes(rps_syear)$lat),
                                               londim = lon_dim,
                                               latdim = lat_dim,
                                               na.rm = F)
                                }, simplify = 'array')
            
            rps_clim_syear <- sapply(X = 1:length(regions), 
                                     FUN = function(X) {
                                       WeightedMean(data = rps_clim_syear,
                                                    region = regions[[X]],
                                                    lon = as.vector(attributes(rps_clim_syear)$lon),
                                                    lat = as.vector(attributes(rps_clim_syear)$lat),
                                                    londim = lon_dim,
                                                    latdim = lat_dim,
                                                    na.rm = F)
                                     }, simplify = 'array')
            
            ## Include name of region dimension
            names(dim(rps_syear))[length(dim(rps_syear))] <- 'region'
            names(dim(rps_clim_syear))[length(dim(rps_clim_syear))] <- 'region'
      
            ## Calculate significance
            sign_rpss <- RandomWalkTest(rps_syear, rps_clim_syear, 
                                        time_dim = time_dim, test.type = 'two.sided',
                                        alpha = alpha, pval = FALSE, sign = TRUE, 
                                        ncores = NULL)$sign
            
            ## Temporally aggregate data
            rps_syear <- Apply(data = rps_syear, 
                                   target_dims = time_dim, 
                                   fun = 'mean', ncores = ncores)$output1
            
            rps_clim_syear <- Apply(data = rps_clim_syear, 
                                        target_dims = time_dim,
                                        fun = 'mean',  ncores = ncores)$output1
            
            ## Calculate RPSS from aggregated RPS and RPS_clim
            rpss <- 1 - rps_syear / rps_clim_syear

            ## Save metric result in arrays
            aggregated_metrics[sys, ref, , , ,which(metrics.visualize == met)] <- s2dv::Reorder(data = rpss, order = c('time', 'sdate','region'))
            metrics_significance[sys, ref, , , , which(metrics.visualize == met)] <- s2dv::Reorder(data = sign_rpss, order = c('time', 'sdate','region'))
            
          } ## close if on rpss
        
          if(met == 'crpss'){
            
            ## Load data from saved files
            crps_syear <- .loadmetrics(input_path = skill.input.path, system = system[sys],
                                      reference = reference[ref], var = var, 
                                      period = period, start_months = start.months,
                                      calib_method = calib.method, metric = 'crps_syear')

            crps_clim_syear <- .loadmetrics(input_path = skill.input.path, system = system[sys],
                                           reference = reference[ref], var = var, 
                                           period = period, start_months = start.months,
                                           calib_method = calib.method, metric = 'crps_clim_syear')

            ## Spatially aggregate data
            crps_syear <- sapply(X = 1:length(regions), 
                                 FUN = function(X) {
                                   WeightedMean(data = crps_syear,
                                                region = regions[[X]],
                                                lon = as.vector(attributes(crps_syear)$lon),
                                                lat = as.vector(attributes(crps_syear)$lat),
                                                londim = lon_dim,
                                                latdim = lat_dim,
                                                na.rm = na.rm)
                                 }, simplify = 'array')
            
            crps_clim_syear <- sapply(X = 1:length(regions), 
                                      FUN = function(X) {
                                        WeightedMean(data = crps_clim_syear,
                                                     region = regions[[X]],
                                                     lon = as.vector(attributes(crps_clim_syear)$lon),
                                                     lat = as.vector(attributes(crps_clim_syear)$lat),
                                                     londim = lon_dim,
                                                     latdim = lat_dim,
                                                     na.rm = na.rm)
                                      }, simplify = 'array')
            
            ## Include name of region dimension
            names(dim(crps_syear))[length(dim(crps_syear))] <- 'region'
            names(dim(crps_clim_syear))[length(dim(crps_clim_syear))] <- 'region'
            
            ## Calculate significance
            sign_crpss <- RandomWalkTest(crps_syear, crps_clim_syear, 
                                         time_dim = time_dim, test.type = 'two.sided',
                                         alpha = alpha, pval = FALSE, sign = TRUE, 
                                         ncores = NULL)$sign
            
            ## Temporally aggregate data
            crps_syear <- Apply(data = crps_syear, 
                                   target_dims = time_dim, 
                                   fun = 'mean', ncores = ncores)$output1
            
            crps_clim_syear <- Apply(data = crps_clim_syear, 
                                        target_dims = time_dim,
                                        fun = 'mean', ncores = ncores)$output1
            
            ## Calculate CRPSS from aggregated CRPS and CRPS_clim
            crpss <- 1 - crps_syear / crps_clim_syear
            
            ## Save metric result in arrays
            aggregated_metrics[sys, ref, , , , which(metrics.visualize == met)] <- s2dv::Reorder(data = crpss, order = c('time', 'sdate','region'))
            metrics_significance[sys, ref, , , , which(metrics.visualize == met)] <- s2dv::Reorder(data = sign_crpss, order = c('time', 'sdate','region'))
            
          } ## close if on crpss
      
          if(met == 'enscorr'){
            ## Load data from saved files
            cov <- .loadmetrics(input_path = stats.input.path, system = system[sys],
                                      reference = reference[ref], var = var, 
                                      period = period, start_months = start.months,
                                      calib_method = calib.method, metric = 'cov')
            
            std_hcst <- .loadmetrics(input_path = stats.input.path, system = system[sys],
                                     reference = reference[ref], var = var, 
                                     period = period, start_months = start.months,
                                     calib_method = calib.method, metric = 'std_hcst')

            std_obs <- .loadmetrics(input_path = stats.input.path, system = system[sys],
                                    reference = reference[ref], var = var, 
                                    period = period, start_months = start.months,
                                    calib_method = calib.method, metric = 'std_obs') 

            
            n_eff <- .loadmetrics(input_path = stats.input.path, system = system[sys],
                                  reference = reference[ref], var = var, 
                                  period = period, start_months = start.months,
                                  calib_method = calib.method, metric = 'n_eff')

            ## Calculate spatial aggregation
            cov <- sapply(X = 1:length(regions), 
                          FUN = function(X) {
                            WeightedMean(data = cov,
                                         region = regions[[X]],
                                         lon = as.vector(attributes(cov)$lon),
                                         lat = as.vector(attributes(cov)$lat),
                                         londim = lon_dim,
                                         latdim = lat_dim,
                                         na.rm = na.rm)
                          }, simplify = 'array')
            
            ## Include name of region dimension
            names(dim(cov))[length(dim(cov))] <- 'region'
            
    
            std_hcst <- sapply(X = 1:length(regions), 
                               FUN = function(X) {
                                 WeightedMean(data = std_hcst,
                                              region = regions[[X]],
                                              lon = as.vector(attributes(std_hcst)$lon),
                                              lat = as.vector(attributes(std_hcst)$lat),
                                              londim = lon_dim,
                                              latdim = lat_dim,
                                              na.rm = na.rm)
                               }, simplify = 'array')
            
            names(dim(std_hcst))[length(dim(std_hcst))] <- 'region'
            
            std_obs <- sapply(X = 1:length(regions), 
                              FUN = function(X) {
                                WeightedMean(data = std_obs,
                                             region = regions[[X]],
                                             lon = as.vector(attributes(std_obs)$lon),
                                             lat = as.vector(attributes(std_obs)$lat),
                                             londim = lon_dim,
                                             latdim = lat_dim,
                                             na.rm = na.rm)
                              }, simplify = 'array')
            
            names(dim(std_obs))[length(dim(std_obs))] <- 'region'
            
            n_eff <- sapply(X = 1:length(regions), 
                            FUN = function(X) {
                              WeightedMean(data = n_eff,
                                           region = regions[[X]],
                                           lon = as.vector(attributes(n_eff)$lon),
                                           lat = as.vector(attributes(n_eff)$lat),
                                           londim = lon_dim,
                                           latdim = lat_dim,
                                           na.rm = na.rm)
                            }, simplify = 'array')
            
            names(dim(n_eff))[length(dim(n_eff))] <- 'region'

            ## Calculate correlation
            enscorr <- cov / (std_hcst * std_obs)

            ## Calculate significance of corr
            t_alpha2_n2 <- qt(p = alpha/2, df = n_eff-2, lower.tail = FALSE)
            t <- abs(enscorr) * sqrt(n_eff-2) / sqrt(1-enscorr^2)
            
            sign_corr<- array(data = NA, 
                              dim = c(time = length(forecast.months), 
                                      sdate = length(start.months), 
                                      region = length(regions)))
            
            for (time in 1:dim(sign_corr)[['time']]){
              for (mon in 1:dim(sign_corr)[['sdate']]){
                for (reg in 1:dim(sign_corr)[['region']]){
            
                  if (anyNA(c(t[time, mon, reg], t_alpha2_n2[time, mon, reg])) == FALSE 
                      && t[time, mon, reg] >= t_alpha2_n2[time, mon, reg]){
                    sign_corr[time, mon, reg] <- TRUE
                  } else {
                    sign_corr[time, mon, reg] <- FALSE
                  }
                }
              }
            }  
    
            ## Save metric result in arrays
            aggregated_metrics[sys, ref, , , , which(metrics.visualize == met)] <- s2dv::Reorder(data = enscorr, order = c('time', 'sdate','region'))
            metrics_significance[sys, ref, , , , which(metrics.visualize == met)] <- s2dv::Reorder(data = sign_corr, order = c('time', 'sdate','region'))
     
          } ## close if on enscorr
         
          if(met == 'mean_bias'){
            
            mean_bias <- .loadmetrics(input_path = skill.input.path, system = system[sys],
                                      reference = reference[ref], var = var, 
                                      period = period, start_months = start.months,
                                      calib_method = calib.method, metric = 'mean_bias')
            
            ## Calculate spatial aggregation
            mean_bias <- sapply(X = 1:length(regions), 
                                       FUN = function(X) {
                                         WeightedMean(data = mean_bias,
                                                      region = regions[[X]],
                                                      lon = as.vector(attributes(mean_bias)$lon),
                                                      lat = as.vector(attributes(mean_bias)$lat),
                                                      londim = lon_dim,
                                                      latdim = lat_dim,
                                                      na.rm = na.rm)
                                       }, simplify = 'array')
            
            names(dim(mean_bias))[length(dim(mean_bias))] <- 'region'
 
            ## Save metric result in array
            aggregated_metrics[sys, ref, , , , which(metrics.visualize == met)] <- s2dv::Reorder(data = mean_bias, order = c('time', 'sdate','region'))
            
          } ## close on mean_bias
                
          if(met == 'enssprerr'){
            
            enssprerr <- .loadmetrics(input_path = skill.input.path, system = system[sys],
                                      reference = reference[ref], var = var, 
                                      period = period, start_months = start.months,
                                      calib_method = calib.method, metric = 'enssprerr')
            
            ## Calculate spatial aggregation
            enssprerr <- sapply(X = 1:length(regions), 
                                             FUN = function(X) {
                                               WeightedMean(data = enssprerr,
                                                            region = regions[[X]],
                                                            lon = as.vector(attributes(enssprerr)$lon),
                                                            lat = as.vector(attributes(enssprerr)$lat),
                                                            londim = lon_dim,
                                                            latdim = lat_dim,
                                                            na.rm = na.rm)
                                             }, simplify = 'array')
            
            names(dim(enssprerr))[length(dim(enssprerr))] <- 'region'
 
            ## Save metric result in array
            aggregated_metrics[sys, ref, , , , which(metrics.visualize == met)] <- s2dv::Reorder(data = enssprerr, order = c('time', 'sdate','region'))
            
          } ## close on enssprerr
        
        } ## close loop on metric
      } ## close if on reference
    } ## close if on system
        
     ## Include metric attributes
     attributes(aggregated_metrics)$metrics <- metrics.visualize
     
     ## Set NAs to False 
     metrics_significance[is.na(metrics_significance)] <- FALSE
     
  } ## close if on score   
  
  
  ####### PLOT SCORECARDS ##########

  ## 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,
                                       sign = metrics_significance,
                                       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,
                                       plot.legend = plot.legend,
                                       legend.breaks = legend.breaks,
                                       legend.white.space = legend.white.space, 
                                       legend.width = legend.width,
                                       legend.height = legend.height,
                                       label.scale = label.scale,
                                       col1.width = col1.width,
                                       col2.width = col2.width,
                                       columns.width = columns.width,
                                       font.size = font.size,
                                       round.decimal = round.decimal,
                                       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,
                                       sign = metrics_significance,
                                       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,
                                       plot.legend = plot.legend,
                                       legend.breaks = legend.breaks,
                                       legend.white.space = legend.white.space, 
                                       legend.width = legend.width,
                                       legend.height = legend.height,
                                       label.scale = label.scale,
                                       col1.width = col1.width,
                                       col2.width = col2.width,
                                       columns.width = columns.width,
                                       font.size = font.size,
                                       round.decimal = round.decimal,
                                       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
  
}

