# This function aims to convert units
## 
source("modules/Units/R/units_transform.R")
source("modules/Units/R/transform_units_temperature.R")
source("modules/Units/R/transform_units_precipitation.R")
source("modules/Units/R/transform_units_pressure.R")
# Requires recipe to include:
# recipe$Analysis$Variables:
# $freq
# $flux (if precipitation)
# $units (optional)
Units <- function(recipe, data) {
  # from recipe read the user defined units
  # from data the original units
  # deaccumulate option for CDS accumulated variables?
  ncores <- recipe$Analysis$ncores
  ## Do we need to convert other than ECVs?
  var_names <- lapply(data, function(x) {x$attrs$Variable$varName})
  freq <- recipe$Analysis$Variable$freq
  if (is.null(recipe$Analysis$Variable$flux)) {
    flux <- FALSE
  } else {
    flux <- recipe$Analysis$Variable$flux
  }
  orig_units <- vector('list', length = length(data))
  names(orig_units) <- names(var_names)
  for (element in names(var_names)) {
    for (x in var_names[[element]]) {
      orig_units[[element]] <- c(orig_units[[element]], 
                                 data[[element]]$attrs$Variable$metadata[[x]]$units)
    }
  }
  if (is.null(recipe$Analysis$Variables$units)) {
    user_units <- orig_units[[which(!is.null(orig_units))[1]]]
  } else {
    user_units <- recipe$Analysis$Variables$units
    if (!is.null(names(user_units))) {
      # Change to vector and ensure that the units are in the correct order
      user_units <- unlist(user_units[var_names[[1]]])
    } else if (length(var_names[[1]] > 1)) {
      ## TODO: How to handle spaces in multi-var case?
      user_units <- strsplit(recipe$Analysis$Variables$units, ", |,")[[1]]
    }
  }
  # remove spaces, "**", "*" and "per" from units
  user_units <- tolower(user_units) 
  user_units <- gsub(" ", "", user_units)
  user_units <- gsub("\\**", "", user_units)
  user_units <- gsub("\\*", "", user_units)
  orig_units <- lapply(orig_units, function(x) {
                       if (!is.null(x)) {
                         x <- tolower(x)
                         x <- gsub(" ", "", x)
                         x <- gsub("\\**", "", x)
                         x <- gsub("\\*", "", x)
                       }
                       }) 
  ## TODO:
  ## if "/" appears substitute by -1 in at the end of next unit. How to know?
  # Check if all units are equal (if so, no conversion needed; else convert)
  if (length(unique(c(unlist(orig_units), user_units))) == length(user_units)) {
    info(recipe$Run$logger, "##### NO UNIT CONVERSION NEEDED #####")
    res <- data
  } else {
    if (recipe$Run$filesystem == 'esarchive' &&
        (sum(!sapply(unique(orig_units), is.null)) != 1)) {
     warn(recipe$Run$logger, 
           paste("The units in", paste(names(orig_units), collapse = ', '),
                 "were not all equal and will be uniformized.",
                 "If this is not expected, please contact the ES data team."))
    }
    res <- sapply(1:length(data), function(x) {
                  if (!is.null(data[[x]])) {
                    if (!all(orig_units[x] == user_units)) {
                      result <- units_transform(data[x], 
                                                orig_units = orig_units[[x]],
                                                user_units = user_units, 
                                                var_names[[x]], freq = freq,
                                                flux = flux,
                                                ncores = ncores)
                    } else {
                      result <- data[x]
                    }
                  } else {
                    result <- data[x]
                  }
                  return(result)
                  }, simplify = TRUE) # instead of lapply to get the named list directly
    info(recipe$Run$logger, "##### UNIT CONVERSION COMPLETE #####")
  }
  return(res)
}
