#----------------------------------------------------------------------------------
# Use gribr package to load GRIB files
# Assume that all the messages have the same metadata; one message is one time step
# If exp, has.memb is a number; if obs, has.memb = NULL
# syear_time_dim is the time attr dim of exp as the input for obs
#----------------------------------------------------------------------------------
source("modules/Loading/R/GRIB/grbload.R")
GrbLoad <- function (dat, time_step = 1, has.memb = NULL, syear_time_dim = NULL,
                     regrid = NULL) {
  library(gribr)

  result <- vector('list', length = length(dat))
  times <- vector('list', length = length(dat))
  times <- lapply(times, '[<-', rep(NA, length(time_step))) #NOTE: length is 0 (slower in loop?)
#  times <- lapply(times, '[<-', .POSIXct(rep(NA, length(time_step)), tz = 'UTC'))

  for (dat_i in 1:length(dat)) {
    
    file_to_load <- tryCatch(grbload(dat[[dat_i]], time_step = time_step,
			      has.memb = has.memb,
			      syear_time_dim = syear_time_dim,
			      regrid = regrid, first_file = dat_i),
			    error=function(e) {
                              warning(paste('Missing file?', e))
			      list(result = NULL, time = NULL)
                            })
    result[[dat_i]] <- file_to_load$result
    times[[dat_i]] <- file_to_load$time
  }  #for loop dat
  # If there are missing files it keeps loading available data
  missing_files <- unlist(lapply(result, function(x) {is.null(x)}))
  if (all(missing_files == TRUE)) {
    error(recipe$Run$logger,
          "Any GRIB file found")
  }
  print(missing_files)
  index <- 1 # using information from first file
  if (any(missing_files == TRUE)) {
    index <- which(missing_files == FALSE)[1]
    for (missed in 1:(which(missing_files))) {
      info(recipe$Run$logger,
	   "There are missing files in grib format.")
      info(recipe$Run$logger,
	   dat[missing_files])
      print(index)
      result[[missed]] <- array(NA, dim(result[[index]]))
    }
  }
  print(index)
  # Turn result list into array
  attr <- attributes(result[[index]])
  res_dim <- c(dim(result[[index]]), syear = length(result)) #[longitude, latitude, (memb*)time, syear]
  result <- unlist(result)
  dim(result) <- res_dim

  # Generate date/time attributes
  times <- array(unlist(times), dim = c(time = length(time_step), syear = length(dat),
                                        sday = 1, sweek = 1))
  times <- s2dv::Reorder(times, c('sday', 'sweek', 'syear', 'time'))
  if (!is.null(syear_time_dim)) dim(times) <- syear_time_dim
  times <- as.POSIXct(times, origin = '1970-01-01', tz = 'UTC')

  # Reshape and reorder array
  if (is.null(has.memb) || has.memb == FALSE) {  # obs doesn't have memb; reshape syear/time dim
    result <- s2dv::Reorder(result, c("syear", "time", "latitude", "longitude"))
    result <- array(result, dim = c(dat = 1, var = 1, 
                                    syear_time_dim, dim(result)[3:4],
				    ensemble = 1))
  } else {
    nmemb <- as.numeric(dim(result)[3])/length(time_step)
    result <- array(result, dim = c(dim(result)[1:2], ensemble = nmemb,
                                    time = length(time_step), dim(result)[4]))
    result <- s2dv::Reorder(result, c("syear", "time", "latitude", "longitude", "ensemble"))
    dim(result) <- c(dat = 1, var = 1, sday = 1, sweek = 1, dim(result))
  }

  # Add attributes back
  attr$dim <- dim(result)
  attributes(result) <- attr
  attr(result, 'time') <- times

  # Save memory
  rm(times); rm(attr); gc()

  return(result)
}

#########################################################################
#########################################################################

.grib_expand_grids <- function(gribMessages, vector = FALSE) {
  # gribMessages is a list of multiple messages
  gribMessage <- gribMessages[[1]]

  if (gribr::has.key(gribMessage, "Nx") && gribr::has.key(gribMessage, "Ny")) {
    nx <- gribMessage$Nx
    ny <- gribMessage$Ny
  } else {
    nx <- gribMessage$Ni
    ny <- gribMessage$Nj
  }

  if (is.null(nx) || is.null(ny)) {
    stop("Unsupported grid type: ", gribMessage$gridType)
  }

  if (grepl("reduced", gribMessage$gridType)) {
    #TODO: This part is not used now. 
    nx <- ny * 2
    values <- .Call("gribr_redtoreg", nx, gribMessage$pl,
                    gribMessage$values)
    values <- matrix(values, nx, ny,
                     byrow = gribMessage$jPointsAreConsecutive)

#    values_l <- vector('list', length = length(gribMessages))
#    for (gm_i in 1:length(gribMessages)) {
#      values <- .Call("gribr_redtoreg", nx, gribMessages[[gm_i]]$pl, 
#                      gribMessages[[gm_i]]$values)
#      values <- matrix(values, nx, ny,
#                       byrow = gribMessage$jPointsAreConsecutive)
#      values_l[[gm_i]] <- values
#    }

  } else {
#    values <- matrix(gribMessage$values, nx, ny,
#                     byrow = gribMessage$jPointsAreConsecutive)
    values_l <- lapply(gribMessages, '[[', 'values')
    values_l <- lapply(values_l, matrix, nx, ny, byrow = gribMessage$jPointsAreConsecutive)
    values <- array(unlist(values_l), dim = c(longitude = nx, latitude = ny, time = length(values_l)))
  }

  if (vector) {
    values <- as.numeric(values)
  }

  values
}


tune_var_name <- function(x) {
  if (x == '2t') {
    res <- "tas"
  } else if (x == 'tprate') {
    res <- "prlr"
  } else if (x == "10si") {
    res <- "sfcWind"
  } else if (x == "2d") {
    res <- "tdps"
  } else if (x == "msl") {
    res <- "psl"
  } else if (x == "sst") {
    res <- "tos"
  } else if (x == "tp") {
    res <- "prlr"
  } else if (x == "mx2t24") {
    res <- "tasmax"
  } else if (x == "mn2t24") {
    res <- "tasmin"
  } else if (x == "Maximum temperature at 2 metres since previous post-processing") {
    res <- "tasmax"
  } else if (x == "Minimum temperature at 2 metres since previous post-processing") {
    res <- "tasmin"
  } else {
    res <- x
    warning("Conversion name", x, "needed?")
  }
  return(res)
}
