.CheckIndices <- function(x, allow_indices = TRUE) {
  x
}

.Load <- function(..., pattern_dim = NULL, file_dims = NULL,
                  default_transform  = .CheckIndices,
                  file_opener = nc_open) {
                  #, config_file = NULL
                  #, variable_dim = , 
                  #file_dimnames = , return_vars = ) {
  dim_params <- list(...)
  # Split *_var parameters
  var_params_ind <- grep('_var$', names(dim_params))
  var_params <- dim_params[var_params_ind]
  # Check all *_var are NULL or vectors of character strings, and 
  # that they all have a matching dimension param.
  i <- 1
  for (var_param in var_params) {
    if (!is.null(var_param)) {
      if (!is.character(var_param)) {
        stop("All '*_var' parameters must be vectors of character strings or NULL.")
      } else if (!any(grepl(paste0('^', strsplit(names(var_params)[i], 
                                                 '_var$')[[1]][1], '$'),
                            names(dim_params)))) {
        stop(paste0("All '*_var' parameters must be associated to a dimension parameter. Found parameter '", 
                    names(var_params)[i], "' but no parameter '", 
                    strsplit(names(var_params)[i], '_var$')[[1]][1], "'."))
      }
    }
    i <- i + 1
  }
  # Split *_transform parameters
  trans_params_ind <- grep('_transform$', names(dim_params))
  trans_params <- dim_params[trans_params_ind]
  # Check all *_transform are NULL or functions, and that they all have 
  # a matching dimension param.
  i <- 1
  for (trans_param in trans_params) {
    if (!is.null(trans_param)) {
      if (!is.function(trans_param)) {
        stop("All '*_transform' parameters must be functions or NULL.")
      } else if (!any(grepl(paste0('^', strsplit(names(trans_params)[i], 
                                                 '_transform$')[[1]][1], '$'),
                            names(dim_params)))) {
        stop(paste0("All '*_transform' parameters must be associated to a dimension parameter. Found parameter '", 
                    names(trans_params)[i], "' but no parameter '", 
                    strsplit(names(trans_params)[i], '_transform$')[[1]][1], "'."))
      }
    }
    i <- i + 1
  }
  # Leave alone the dimension parameters
  if (length(c(var_params_ind, trans_params_ind)) > 0) {
    dim_params <- dim_params[-c(var_params_ind, trans_params_ind)]
  }
  dim_names <- names(dim_params)
  # Make the keys of 'var_params' and 'trans_params' to be the name of 
  # the corresponding dimension.
  names(var_params) <- gsub('_var$', '', names(var_params))
  names(trans_params) <- gsub('_transform$', '', names(trans_params))

  # Check pattern_dim
  if (is.null(pattern_dim)) {
    print(paste0("Parameter 'pattern_dim' not specified. Taking the first dimension, '", 
                 dim_names[1], "' as 'pattern_dim'."))
    pattern_dim <- dim_names[1]
  } else if (is.character(pattern_dim)) {
    if (length(pattern_dim) > 1) {
      print(paste0("There can be only one 'pattern_dim'. Taking '", pattern_dim[1], 
                   "' as pattern dimension."))
    }
    pattern_dim <- pattern_dim[1]
  } else {
    stop("Parameter 'pattern_dim' must be a character string.")
  }

  # Check file_dims
  if (is.null(file_dims)) {
    file_dims <- pattern_dim
  } else if (is.character(file_dims)) {
    if(any(!(file_dims %in% dim_names))) {
      stop("All names in parameter 'file_dims' must be valid dimension names.")
    }
    if (!(pattern_dim %in% file_dims)) {
      file_dims <- c(file_dims, pattern_dim)
    }
    ## TODO: Order file_dims in function of dim_names
  }
  
## TODO: varmin and varmax
  # Check all specifications in pattern_dim are valid
  dat <- datasets <- dim_params[[pattern_dim]]
  if (is.null(dat) || !(is.character(dat) && all(nchar(dat) > 0)) && !is.list(dat)) {
    stop(paste0("Parameter '", pattern_dim, 
                "' must be a list of lists with pattern specifications or a vector of character strings."))
  }
  if (!is.null(trans_params[[pattern_dim]])) {
    print(paste0("A transformation for the indices of '", pattern_dim, 
                 "' has been specified, but it is the pattern dimension and the transformation will be ignored."))
  }
  dat_info_names <- c('name', 'path')#, 'nc_var_name', 'suffix', 'var_min', 'var_max', 'dimnames')
  dat_to_fetch <- c()
  dat_names <- c()
  if (!is.list(dat)) {
    dat <- lapply(dat, function (x) list(name = x))
  }
  for (i in 1:length(dat)) {
    if (is.character(dat[[i]]) && length(dat[[i]]) == 1 && nchar(dat[[i]]) > 0) {
      dat[[i]] <- list(name = dat[[i]])
    } else if (!is.list(dat[[i]])) {
      stop(paste0("Parameter '", pattern_dim, 
                  "' is incorrect. It must be a list of lists or character strings."))
    }
    #if (!(all(names(dat[[i]]) %in% dat_info_names))) {
    #  stop("Error: parameter 'dat' is incorrect. There are unrecognized components in the information of some of the dateriments. Check 'dat' in ?Load for details.")
    #}
    if (!('name' %in% names(dat[[i]]))) {
      dat[[i]][['name']] <- paste0('dat', i)
      if (!('path' %in% names(dat[[i]]))) {
        stop(paste0("Parameter '", pattern_dim, 
                    "' is incorrect. A 'path' should be provided for each dataset if no 'name' is provided."))
      }
    } else if (!('path' %in% names(dat[[i]]))) {
      dat_to_fetch <- c(dat_to_fetch, i)
    }
    #if ('path' %in% names(dat[[i]])) {
    #  if (!('nc_var_name' %in% names(dat[[i]]))) {
    #    dat[[i]][['nc_var_name']] <- '$var_name$'
    #  }
    #  if (!('suffix' %in% names(dat[[i]]))) {
    #    dat[[i]][['suffix']] <- ''
    #  }
    #  if (!('var_min' %in% names(dat[[i]]))) {
    #    dat[[i]][['var_min']] <- ''
    #  }
    #  if (!('var_max' %in% names(dat[[i]]))) {
    #    dat[[i]][['var_max']] <- ''
    #  }
    #}
    dat_names <- c(dat_names, dat[[i]][['name']])
  }
  if ((length(dat_to_fetch) > 0) && (length(dat_to_fetch) < length(dat))) {
    print("'path' has been provided for some datasets. Any information in the configuration file related to these will be ignored.")
  }

  ## check config_file
  ### TODO: Get rid of this default
  #if (is.null(config_file)) {
  #  config_file <- system.file("config", "BSC.conf", package = "s2dverification")
  #} else if (!is.character(config_file) || !(nchar(config_file) > 0)) {
  #  stop("Error: parameter 'config_file' must be a character string with the path to a .Load() configuration file, if provided.")
  #}

  ## If not all data has been provided for any of the datasets in the 
  ## pattern_dim, configuration file is read.
  #if (length(dat_to_fetch) > 0) {
  #  print(paste0("Some 'path's not explicitly provided in '", pattern_dim, 
  #               "', so will now proceed to open the configuration file.")
  #  data_info <- ConfigFileOpen(config_file, silent, TRUE)
  #
  #  # Check that the var, exp and obs parameters are right and keep the entries
  #  # that match for each dataset.
  #  # Afterwards, the matching entries are applied sequentially (as specified 
  #  # in ?ConfigFileOpen) and the replace_values are applied to the result.
  #  # Finally a path pattern for each dataset is provided.
  #  matches <- ConfigApplyMatchingEntries(data_info, var, sapply(exp[exps_to_fetch], '[[', 'name'),
  #               sapply(obs[obs_to_fetch], '[[', 'name'), show_entries = FALSE, show_result = FALSE)
  #  # 'replace_values' is a named list that associates a variable name to an 
  #  # associated value. Initially it is filled with variables and values parsed
  #  # from the configuration file, but we can add or modify some values during
  #  # the execution to choose for example which start date we want to load.
  #  # When '.ConfigReplaceVariablesInString' is called, all the variable accesses 
  #  # ($VARIABLE_NAME$) that appear in the string given as parameter are 
  #  # replaced by the associated value in 'replace_values'.
  #  replace_values <- data_info$definitions
  #  if (!is.null(exp) && length(exps_to_fetch) > 0) {
  #    counter <- 1
  #    exp[exps_to_fetch] <- lapply(matches$exp_info,
  #      function (x) {
  #        x[names(exp[[exps_to_fetch[counter]]])] <- exp[[exps_to_fetch[counter]]]
  #        x[['path']] <- paste0(x[['main_path']], x[['file_path']])
  #        counter <<- counter + 1
  #        x
  #      })
  #  }
  #  if (!is.null(obs) && length(obs_to_fetch) > 0) {
  #    counter <- 1
  #    obs[obs_to_fetch] <- lapply(matches$obs_info,
  #      function (x) {
  #        x[names(obs[[obs_to_fetch[counter]]])] <- obs[[obs_to_fetch[counter]]]
  #        x[['path']] <- paste0(x[['main_path']], x[['file_path']])
  #        counter <<- counter + 1
  #        x
  #      })
  #  }
  #  if (!silent) {
  #    .message("All pairs (var, exp) and (var, obs) have matching entries.")
  #  }
  #} else {
  #  replace_values <- list(DEFAULT_NC_VAR_NAME = '$VAR_NAME$',
  #                         DEFAULT_VAR_MIN = '',
  #                         DEFAULT_VAR_MAX = '',
  #                         DEFAULT_SUFFIX = '',
  #                         DEFAULT_DIM_NAME_LONGITUDES = 'longitude',
  #                         DEFAULT_DIM_NAME_LATITUDES = 'latitude',
  #                         DEFAULT_DIM_NAME_MEMBERS = 'ensemble')
  #}
  ## We take the dimnames that haven't been explicitly specified from the 
  ## configuration file.
  ## If the configuration file wasn't opened, we take the default values from
  ## the dictionary 'replace_values'.
  #dimnames <- list(lon = ifelse(is.null(dimnames[["lon"]]),
  #                              replace_values[["DEFAULT_DIM_NAME_LONGITUDES"]],
  #                              dimnames[['lon']]),
  #                 lat = ifelse(is.null(dimnames[["lat"]]),
  #                              replace_values[["DEFAULT_DIM_NAME_LATITUDES"]],
  #                              dimnames[['lat']]),
  #                 member = ifelse(is.null(dimnames[["member"]]),
  #                                 replace_values[["DEFAULT_DIM_NAME_MEMBERS"]],
  #                                 dimnames[['member']]))
  #mandatory_defaults <- c('DEFAULT_EXP_MAIN_PATH', 'DEFAULT_EXP_FILE_PATH',
  #                        'DEFAULT_OBS_MAIN_PATH', 'DEFAULT_OBS_FILE_PATH',
  #                        'DEFAULT_NC_VAR_NAME', 'DEFAULT_SUFFIX',
  #                        'DEFAULT_VAR_MIN', 'DEFAULT_VAR_MAX',
  #                        'DEFAULT_DIM_NAME_LONGITUDES',
  #                        'DEFAULT_DIM_NAME_LATITUDES',
  #                        'DEFAULT_DIM_NAME_MEMBERS')
  #extra_vars_with_default_ind <- (1:length(replace_values))[grep('^DEFAULT_', names(replace_values))]
  #extra_vars_with_default_ind <- extra_vars_with_default_ind[
  #                                 grep(paste0(paste0('^', mandatory_defaults),
  #                                             collapse = '|'),
  #                                      names(replace_values)[extra_vars_with_default_ind],
  #                                      invert = TRUE)
  #                               ]
  #extra_vars_with_default <- gsub('^DEFAULT_', '',
  #                                names(replace_values)[extra_vars_with_default_ind])
  #if (!is.null(exp)) {
  #  exp <- lapply(exp, function (x) {
  #    if (!('dimnames' %in% names(x))) {
  #      x[['dimnames']] <- dimnames
  #    } else {
  #      dimnames2 <- dimnames
  #      dimnames2[names(x[['dimnames']])] <- x[['dimnames']]
  #      x[['dimnames']] <- dimnames2
  #    }
  #    i <- 1
  #    while (i <= length(extra_vars_with_default)) {
  #      if (!(extra_vars_with_default[i] %in% names(x))) {
  #        x[[extra_vars_with_default[i]]] <- replace_values[[extra_vars_with_default_ind[i]]]
  #      }
  #      i <- i + 1
  #    }
  #    x
  #  })
  #}
  #if (!is.null(obs)) {
  #  obs <- lapply(obs, function (x) {
  #    if (!('dimnames' %in% names(x))) {
  #      x[['dimnames']] <- dimnames
  #    } else {
  #      dimnames2 <- dimnames
  #      dimnames2[names(x[['dimnames']])] <- x[['dimnames']]
  #      x[['dimnames']] <- dimnames2
  #    }
  #    i <- 1
  #    while (i <= length(extra_vars_with_default)) {
  #      if (!(extra_vars_with_default[i] %in% names(x))) {
  #        x[[extra_vars_with_default[i]]] <- replace_values[[extra_vars_with_default_ind[i]]]
  #      }
  #      i <- i + 1
  #    }
  #    x
  #  })
  #}
  #single_dataset <- (length(obs) + length(exp) == 1)
  dim_params[[pattern_dim]] <- dat_names

  # Check that no unrecognized variables are present in the path patterns
  # and also that no file dimensions are requested to THREDDs catalogs.
  replace_values <- replicate(length(file_dims), '*')
  names(replace_values) <- dim_names[which(dim_names %in% file_dims)]
  first_dat_with_data <- NULL
  ## TODO: Do a for for all datasets, check if ^http and for those, 
  # check the indices for the file dimensions, with allow_indices = FALSE
  # Keep a variable with marks for the checked indices -> Not possible to check again
  for (i in 1:length(dat)) {
    pattern <- .ConfigReplaceVariablesInString(dat[[i]][['path']], 
                                               replace_values))
    if (length(grep("^http", pattern)) > 0) {
      ## TODO: Check that the user is not using shell globbing exps.
      # if (dat[[i]][['path']] has shell globs) {
      #   stop! no shell globs allowed in path patterns to catalogs
      # }
      fix a value for each file dimension and replace
      if (is.null(first_dat_with_data)) {
        file <- NULL
        file <- file_opener(pattern)
        if (!is.null(file)) {
          first_dat_with_data <- i
        }
      }
    } else {
      is_url <- FALSE
      ## TODO: Improve error message here:
      dat_path_with_globs <- .ConfigReplaceVariablesInString(dat[[i]][['path']], 
                                                             replace_values))
      files <- Sys.glob(filename)
    }
  }
  # We finally keep the one of the first dataset and then, 
  
  ## for each file dimension
  ##   replace shell globbing exps and find out how many files for that dimension there are
  ##   call the check indices function
  ## end for
iterate patterns, values of all dimensions outside the file
  # Check all the indices provided for each dimension
  for (dim_name in dim_names) {
    if (dim_name == pattern_dim) {
      if (!is.null(trans_params[[dim_name]])) {
        print(paste0("A transformation for the indices of '", dim_name, 
                     "' has been specified, but it is the pattern dimension and the transformation will be ignored."))
      }
    } else {
      transformation <- trans_params[[dim_name]]
      if (is.null(transformation)) {
        transformation <- default_transform
      }
      dim_params[[dim_name]] <- transformation(dim_params[[dim_name]])
    }
  }

  list(dim_params, dim_names, var_params, trans_params)
}
