S2dvToDownR <- function(data, collapse_obs = FALSE) {
  # Adapt and format the dates properly.
  # Determine the number of downscaleR objects to be created, if there
  # are overlapping runs.
  if (!is.null(data$Dates)) {
    if (!is.null(data$mod)) {
      dim(data$Dates$start) <- dim(data$mod)[c('ftime', 'sdate')]
      dim(data$Dates$end) <- dim(data$mod)[c('ftime', 'sdate')]
    } else if (!is.null(data$obs)) {
      dim(data$Dates$start) <- dim(data$obs)[c('ftime', 'sdate')]
      dim(data$Dates$end) <- dim(data$obs)[c('ftime', 'sdate')]
    } else {
      stop("Empty object provided.")
    }
    dim_bk <- dim(data$Dates$start)
    new_dates_start <- strftime(data$Dates$start, usetz = TRUE)
    dim(new_dates_start) <- dim_bk
    #new_dates_start <- aperm(new_dates_start, c(2, 1))
    #names(dim(new_dates_start)) <- rev(names(dim_bk))
    
    dim_bk <- dim(data$Dates$end)
    new_dates_end <- strftime(data$Dates$end, usetz = TRUE)
    dim(new_dates_end) <- dim_bk
    #new_dates_end <- aperm(new_dates_end, c(2, 1))
    #names(dim(new_dates_end)) <- rev(names(dim_bk))

    required_downr_objects <- 1
    ftimes_per_downr_object <- dim(new_dates_start)['ftime']
    if (dim(new_dates_start)['sdate'] > 1) {
      if (new_dates_start[dim(new_dates_start)['ftime'], 1] >= 
          new_dates_start[1, 2]) {
        ftimes_per_downr_object <- sum(new_dates_start[, 1] < 
                                       new_dates_start[1, 2])
        required_downr_objects <- ceiling(dim(new_dates_start)['ftime'] / 
                                          ftimes_per_downr_object)
        #stop("The provided 'data' has data for model runs with overlapping",
        #     "forecast times. This is not supported by downscaleR.")
      }
    }
  } else {
    stop("The parameter 'data' must have a 'Dates' component.")
  }

  # Revert latitudes if needed
  # lat_indices will be used afterwards to take the data for each dataset
  if (length(data$lat) > 2) {
    if (data$lat[1] > data$lat[2]) {
      lat_indices <- length(data$lat):1
      attr_bk <- attributes(data$lat)
      data$lat <- rev(data$lat)
      if ('first_lat' %in% names(attr_bk)) {
        attr_bk[c('first_lat', 'last_lat')] <- unname(attr_bk[c('last_lat', 'first_lat')])
      }
    } else {
      lat_indices <- 1:length(data$lat)
    }
  }

  # Convert experimental and observational data.
  new_exps <- list()
  new_obss <- list()
  if (!is.null(data$mod)) {
    exp_names <- names(data$Datasets$exp)
    if (length(dim(data$mod)) != 6) {
      stop("S2dv2DownR not able to translate area averages yet.")
    }
    for (exp_index in 1:dim(data$mod)[1]) {
      new_exps[[exp_names[exp_index]]] <- list()
      ftime_counter <- 0
      for (downr_object in 1:required_downr_objects) {
        object_ftimes <- min(dim(new_dates_start)['ftime'] - ftime_counter, ftimes_per_downr_object)
        new_exp <- NULL
        new_data_exp <- aperm(data$mod[exp_index, , , (ftime_counter + 1):(ftime_counter + object_ftimes), lat_indices, , drop = FALSE], 
                              c(1, 2, 4, 3, 5, 6))
        new_exp_dims <- c(dim(data$mod)[2], 
                          time = prod(dim(new_data_exp)[3:4]), 
                          dim(data$mod)[5:6])
        dim(new_data_exp) <- new_exp_dims
        attr(new_data_exp, 'dimensions') <- names(new_exp_dims)
  
        new_exp <- list(Variable = data$Variable,
                        Data = new_data_exp,
                        xyCoords = list(x = data$lon, 
                                        y = data$lat),
                        Dates = list(start = as.vector(new_dates_start[(ftime_counter + 1):(ftime_counter + object_ftimes), , drop = FALSE]),
                                     end = as.vector(new_dates_end[(ftime_counter + 1):(ftime_counter + object_ftimes), , drop = FALSE])),
                        InitializationDates = data$Datasets$exp[[1]][[1]],
                        Members = data$Datasets$exp[[1]][[2]])
        attr(new_exp$xyCoords, 'projection') <- attr(data$lon, 'projection')
        attr(new_exp, 'dataset') <- attr(data$Dataset$exp[[1]], 'dataset')
        attr(new_exp, 'source') <- attr(data$Dataset$exp[[1]], 'source')
        attr(new_exp, 'URL') <- attr(data$Dataset$exp[[1]], 'URL')
        new_exps[[exp_names[exp_index]]][[paste('ftimes', 1 + ftime_counter, 'to', ftime_counter + object_ftimes)]] <- new_exp
    
        if (!is.null(data$obs)) {
          obs_names <- names(data$Datasets$obs)
          if (length(dim(data$obs)) != 6) {
            stop("S2dv2DownR not able to translate area averages yet.")
          }
          for (obs_index in 1:dim(data$obs)[1]) {
            new_obs <- NULL
            new_data_obs <- aperm(data$obs[obs_index, , , (ftime_counter + 1):(ftime_counter + object_ftimes), lat_indices, , drop = FALSE],
                                  c(1, 2, 4, 3, 5, 6))
            if (dim(data$obs)[2] > 1) {
              stop("S2dv2DownR not able to translate multimember observations yet.")
            }
            new_obs_dims <- c(time = prod(dim(new_data_obs)[3:4]),
                              dim(data$obs)[5:6])
            dim(new_data_obs) <- new_obs_dims
            if (collapse_obs) {
              # Disregard overlapping values for overlapping runs
              unique_dates <- sort(as.numeric(unique(data$Dates$start)), index.return = TRUE)$ix
              new_data_obs <- new_data_obs[unique_dates, , , drop = FALSE]
            }
            attr(new_data_obs, 'dimensions') <- names(new_obs_dims)

            new_obs <- list(Variable = data$Variable,
                            Data = new_data_obs,
                            xyCoords = list(x = data$lon,
                                            y = data$lat),
                            Dates = list(start = as.vector(new_dates_start[(ftime_counter + 1):(ftime_counter + object_ftimes), , drop = FALSE]),
                                         end = as.vector(new_dates_end[(ftime_counter + 1):(ftime_counter + object_ftimes), , drop = FALSE])))
            if (!collapse_obs) {
              new_obs <- c(new_obs, list(InitializationDates = data$Datasets$obs[[1]][[1]],
                                         Members = data$Datasets$obs[[1]][[2]]))
            }
            attr(new_obs$xyCoords, 'projection') <- attr(data$lon, 'projection')
            attr(new_obs, 'dataset') <- attr(data$Dataset$obs[[1]], 'dataset')
            attr(new_obs, 'source') <- attr(data$Dataset$obs[[1]], 'source')
            attr(new_obs, 'URL') <- attr(data$Dataset$obs[[1]], 'URL')
            if (downr_object == 1) {
              new_obss[[obs_names[obs_index]]] <- list()
            }
            new_obss[[obs_names[obs_index]]][[paste('ftimes', 1 + ftime_counter, 'to', ftime_counter + object_ftimes)]] <- new_obs
          }
        }
        ftime_counter <- ftime_counter + object_ftimes
      }
    }
  } else {
    # Convert observational data only if no exp data provided
    obs_names <- names(data$Datasets$obs)
    if (length(dim(data$obs)) != 6) {
      stop("S2dv2DownR not able to translate area averages yet.")
    }
    for (obs_index in 1:dim(data$obs)[1]) {
      new_obs <- NULL
      new_data_obs <- aperm(data$obs[obs_index, , , , lat_indices, , drop = FALSE],
                            c(1, 2, 4, 3, 5, 6))
      if (dim(data$obs)[2] > 1) {
        stop("S2dv2DownR not able to translate multimember observations yet.")
      }
      new_obs_dims <- c(time = prod(dim(new_data_obs)[3:4]),
                        dim(data$obs)[5:6])
      dim(new_data_obs) <- new_obs_dims
      # Disregard overlapping values for overlapping runs
      unique_dates <- sort(as.numeric(unique(data$Dates$start)), index.return = TRUE)$ix
      new_data_obs <- new_data_obs[unique_dates, , , drop = FALSE]
      attr(new_data_obs, 'dimensions') <- names(new_obs_dims)

      new_obs <- list(Variable = data$Variable,
                      Data = new_data_obs,
                      xyCoords = list(x = data$lon,
                                      y = data$lat),
                      Dates = list(start = as.vector(new_dates_start[unique_dates]),
                                   end = as.vector(new_dates_end[unique_dates])))
      if (!collapse_obs) {
        new_obs <- c(new_obs, list(InitializationDates = data$Datasets$obs[[1]][[1]],
                                   Members = data$Datasets$obs[[1]][[2]]))
      }
      attr(new_obs$xyCoords, 'projection') <- attr(data$lon, 'projection')
      attr(new_obs, 'dataset') <- attr(data$Dataset$obs[[1]], 'dataset')
      attr(new_obs, 'source') <- attr(data$Dataset$obs[[1]], 'source')
      attr(new_obs, 'URL') <- attr(data$Dataset$obs[[1]], 'URL')
      if (obs_index == 1) {
        new_obss[[obs_names[obs_index]]] <- new_obs
      }
    }
  }

  list(exp = new_exps, obs = new_obss)
}
