#'CDO Remap Data Transformation for 'startR'
#'
#'This is a transform function that uses CDO software to remap longitude-latitude 
#'data subsets onto a specified target grid, intended for use as parameter 
#''transform' in a Start() call. This function complies with the input/output 
#'interface required by Start() defined in the documentation for the parameter 
#''transform' of function Start().\cr\cr
#'This function uses the function CDORemap() in the package 's2dv' to 
#'perform the interpolation, hence CDO is required to be installed.
#'
#'@param data_array A data array to be transformed. See details in the 
#'  documentation of the parameter 'transform' of the function Start().
#'@param variables A list of auxiliary variables required for the transformation, 
#'  automatically provided by Start(). See details in the documentation of the 
#'  parameter 'transform' of the function Start().
#'@param file_selectors A charcter vector indicating the information of the path of
#'  the file parameter 'data_array' comes from. See details in the documentation of
#'  the parameter 'transform' of the function Start(). The default value is NULL.
#'@param \dots A list of additional parameters to adjust the transform process, 
#'  as provided in the parameter 'transform_params' in a Start() call. See details
#'  in the documentation of the parameter 'transform' of the function Start().
#'
#'@return An array with the same amount of dimensions as the input data array, 
#'  potentially with different sizes, and potentially with the attribute 
#'  'variables' with additional auxiliary data. See details in the documentation 
#'  of the parameter 'transform' of the function Start().
#'@seealso \code{\link[s2dv]{CDORemap}}
#'
#'@examples
#'# Used in Start():
#'  data_path <- system.file('extdata', package = 'startR')
#'  path_obs <- file.path(data_path, 'obs/monthly_mean/$var$/$var$_$sdate$.nc')
#'  sdates <- c('200011')
#'  \donttest{
#'  data <- Start(dat = list(list(path = path_obs)),
#'                var = 'tos',
#'                sdate = sdates,
#'                time = 'all',
#'                latitude = values(list(-60, 60)),
#'                latitude_reorder = Sort(decreasing = TRUE),
#'                longitude = values(list(-120, 120)),
#'                longitude_reorder = CircularSort(-180, 180),
#'                transform = CDORemapper,
#'                transform_params = list(grid = 'r360x181',
#'                                        method = 'conservative'),
#'                transform_vars = c('latitude', 'longitude'),
#'                return_vars = list(latitude = 'dat',
#'                                   longitude = 'dat',
#'                                   time = 'sdate'),
#'                retrieve = FALSE)
#' }
#'@importFrom s2dv CDORemap
#'@export
CDORemapper <- function(data_array, variables, file_selectors = NULL, 
                        crop_domain = NULL, ...) {
  file_dims <- names(file_selectors)
  known_lon_names <- startR:::.KnownLonNames()
  known_lat_names <- startR:::.KnownLatNames()
  if (!any(known_lon_names %in% names(variables)) ||
      !any(known_lat_names %in% names(variables))) {
    stop("The longitude and latitude variables must be requested in ",
         "'return_vars' and specified in 'transform_vars' for the ",
         "CDORemapper to work.")
  }
  lon_name <- names(variables)[which(names(variables) %in% known_lon_names)[1]]
  lons <- variables[[lon_name]]
  if (!is.null(dim(lons))) {
    dims_to_subset <- which(names(dim(lons)) %in% file_dims)
    if (length(dims_to_subset) > 0) {
      lons_to_use <- as.list(rep(TRUE, length(dim(lons))))
      names(lons_to_use) <- names(dim(lons))
      lons_to_use[dims_to_subset] <- as.list(rep(1, length(dims_to_subset)))
      attr_bk <- attributes(lons)
      lons <- do.call('[', c(list(x = lons), lons_to_use, list(drop = TRUE)))
      attributes(lons) <- attr_bk
    }
  }
  lat_name <- names(variables)[which(names(variables) %in% known_lat_names)[1]]
  lats <- variables[[lat_name]]
  if (!is.null(dim(lats))) {
    dims_to_subset <- which(names(dim(lats)) %in% file_dims)
    if (length(dims_to_subset) > 0) {
      lats_to_use <- as.list(rep(TRUE, length(dim(lats))))
      names(lats_to_use) <- names(dim(lats))
      lats_to_use[dims_to_subset] <- as.list(rep(1, length(dims_to_subset)))
      attr_bk <- attributes(lons)
      lats <- do.call('[', c(list(x = lats), lats_to_use, list(drop = TRUE)))
      attributes(lats) <- attr_bk
    }
  }
  extra_params <- list(...)

  if (!all(c('grid', 'method') %in% names(extra_params))) {
    stop("Parameters 'grid' and 'method' must be specified for the ",
         "CDORemapper, via the 'transform_params' argument.")
  }
#-----------NEW-------------
  # Use crop_domain to get 'crop'
  ## lon
  known_lon_names <- startR:::.KnownLonNames()
  lon_name <- names(crop_domain)[which(names(crop_domain) %in% known_lon_names)]
#  if (attr(crop_domain[[lon_name]], 'values')) {
#    if (is.list(crop_domain[[lon_name]])) {
#      crop_lon <- unlist(crop_domain[[lon_name]])
#    } else {  # vector
#      crop_lon <- c(crop_domain[[lon_name]][1], tail(crop_domain[[lon_name]], 1))
#    }
#  } else if (crop_domain[[lon_name]] == 'all') {
#    crop_lon <- c(lons[1], tail(lons, 1))
#  } else {  # indices()
#    if (is.list(crop_domain[[lon_name]])) {
#      crop_lon <- lons[unlist(crop_domain[[lon_name]])]
#    } else {  # vector
#      crop_lon <- c(lons[crop_domain[[lon_name]][1]], 
#                    lons[tail(crop_domain[[lon_name]], 1)])
#    }
#  }
  crop_lon <- unlist(crop_domain[[lon_name]])

#PROBLEM-----------------------------------
  # If lon_reorder is not used and lon selector is from big to small (e.g.,
  # lon is expected to be c(20, 19, ..., 1, 0)), crop_lon need to exchange the order from c(20, 10) to c(10, 20). The 2nd criteria is, if lon_reorder is used,
  # the meridian is crossed and lons will cover the smallest and biggest values; if not, the range of lons will be smaller than the whole region.
  # The third criteria is for an odd Start() call that the longitude selector is not aligned with CircularSort(). E.g., lon = values(20, 10) but lon_reorder = CircularSort(-180, 180). Not sure if it is univerally correct. It's better to know if lon_reorder is used, but in CDORemapper() this info is missing.
#print('lons')
#print(str(lons))
#print('val')
#print(str((attr(lons, 'variables')[[lon_name]]$dim[[1]]$vals)))
  if (crop_lon[1] > crop_lon[2] & 
      diff(range(lons)) != diff(range(attr(lons, 'variables')[[lon_name]]$dim[[1]]$vals)) &
      all(crop_lon >= range(lons)[1] & crop_lon <= range(lons)[2])) {
    crop_lon <- rev(crop_lon)
  }
#PROBLEM-----------------------------------


  ## lat
  known_lat_names <- startR:::.KnownLatNames()
  lat_name <- names(crop_domain)[which(names(crop_domain) %in% known_lat_names)]
#  if (attr(crop_domain[[lat_name]], 'values')) {
#    if (is.list(crop_domain[[lat_name]])) {
#      crop_lat <- unlist(crop_domain[[lat_name]])
#    } else {  # vector
#      crop_lat <- c(crop_domain[[lat_name]][1], tail(crop_domain[[lat_name]], 1))
#    }
#  } else if (crop_domain[[lat_name]] == 'all') {
#    crop_lat <- c(lats[1], tail(lats, 1))
#  } else {  # indices()
#    if (is.list(crop_domain[[lat_name]])) {
#      crop_lat <- lats[unlist(crop_domain[[lat_name]])]
#    } else {  # vector
##lats and indices are both original?? without reorder??
#      crop_lat <- c(lats[crop_domain[[lat_name]][1]], 
#                    lats[tail(crop_domain[[lat_name]], 1)])
#    }
#  }
  crop_lat <- unlist(crop_domain[[lat_name]])
  crop_values <- c(crop_lon, crop_lat)
print('crop_values')
print(crop_values)
  if ('crop' %in% names(extra_params)) {
    .warning("Argument 'crop' in 'transform_params' for CDORemapper() is ",
             "deprecated. It is automatically assigned as the selected .",
             "domain in Start() call.")
  }
  extra_params[['crop']] <- crop_values
 
  result <- do.call(s2dv::CDORemap, c(list(data_array, lons, lats), extra_params))
#  result <- s2dv::CDORemap(data_array, lons, lats, ...)
#-------NEW_END--------------
  return_variables <- list(result$lons, result$lats)
  names(return_variables) <- c(lon_name, lat_name)
  list(data_array = result$data_array, variables = return_variables)
}
