#'Quantiles Mapping for seasonal or decadal forecast data
#'
#'@description This function is a wrapper from fitQmapQUANT and doQmapQUANT from package 'qmap'to be applied in CSTools objects of class 's2dv_cube'.
#'
#'@author Nuria Perez-Zanon, \email{nuria.perez@bsc.es}
#'@param exp an object of class \code{s2dv_cube}
#'@param obs
#'@param wetday logical indicating whether to perform wet day correction or not. OR a numeric
#'@param qstep a numeric value between 0 and 1. The quantile mapping is fitted only for the quantiles defined by quantile(0,1,probs=seq(0,1,by=qstep).
#'@param type type of interpolation between the fitted transformed values. See details.
#'
#'@return an oject of class \code{s2dv_cube} containing the experimental data after applyingthe quantile mapping correction. 
#') <- c(dataset = 1, member = 10, sdate = 20, ftime = 60 , 
#'@import qmap
#'@import multiApply
#'
#'@seealso \code{\link[qmap]{fitQmapQUANT}} and \code{\link[qmap]{doQmapQUANT}}
#'@examples
#'exp$data <- runif(n = 1 * 10 * 20 * 60 * 6 * 7, min = 0, max = 5)
#'dim(exp$data) <- c(dataset = 1, member = 10, sdate = 20, ftime = 60 , 
#'                   lat = 6, lon = 7)
#'class(exp) <- 's2dv_cube'
#'obs$data <- runif(n = 1 * 1 * 20 * 60 * 6 * 7, min = 0, max = 5)
#'dim(obs$data) <- c(dataset = 1, member = 1, sdate = 20, ftime = 60 ,
#'                   lat = 6, lon = 7)
#'class(obs) <- 's2dv_cube'
#'res <- CST_QuantileMapping(exp, obs)
#'exp <- lonlat_data$exp
#'obs <- lonlat_data$obs
#'res <- CST_QuantileMapping(exp, obs)
#'@export
CST_QuantileMapping <- function(exp, obs, wetday = TRUE, qstep = 0.1,
                                type = 'linear') {
    if (!inherits(exp, 's2dv_cube') || !inherits(exp, 's2dv_cube')) {
        stop("Parameter 'exp' and 'obs' must be of the class 's2dv_cube', ",
             "as output by CSTools::CST_Load.")
    }
    dimnames <- names(dim(exp$data))
    QMapped <- QuantileMappingCor(exp = exp$data, obs = obs$data, wetday = wetday,
                                  qstep = qstep, type = type)
    pos <- match(dimnames, names(dim(QMapped)))

    QMapped <- aperm(QMapped, pos)
    names(dim(QMapped)) <- dimnames 
    exp$data <- QMapped
    exp$Datasets <- c(exp$Datasets, obs$Datasets)
    exp$source_files <- c(exp$source_files, obs$source_files)
    return(exp)
}
exp <- 1:20
dim(exp) <- c(lat = 2, lon = 10)
obs <- 101:120
dim(obs) <- c(lat = 2, lon = 10)
QuantileMappingCor(exp, obs)
exp <- 1:20
dim(exp) <- c(lat = 2, lon = 5, member = 2)
obs <- 101:120
dim(obs) <- c(lat = 2, lon = 5, member = 2)
QuantileMappingCor(exp, obs)
QuantileMappingCor <- function(exp, obs, wetday = TRUE, qstep = 0.1,
                               type = 'linear') {
  if (!all(c('lat', 'lon') %in% names(dim(exp)))) {
    stop("Parameter 'exp' must have the dimensions 'lat' and 'lon'.")
  }

  if (!all(c('lat', 'lon') %in% names(dim(obs)))) {
    stop("Parameter 'obs' must have the dimension 'lat' and 'lon.")
  }
  if (any(is.na(exp)))  {
    warning("Parameter 'exp' contains NA values.")
  }  
  if (any(is.na(obs))) {
    warning("Parameter 'obs' contains NA values.")
  }
  if (!is.logical(wetday)) { 
    stop("Parameter 'wetday' must be logical.")
  } 
  if (length(wetday) > 1) {
    warning("Parameter 'wetday' has length > 1 and only the first element",
            " is used.")
    wetday <- wetday[1]
  } 
  if (!is.numeric(qstep)) {
    stop("Parameter 'qstep' must be numeric.")
  }
  if (qstep > 1 | qstep < 0) {
    stop("Parameter 'qstep' must be a numeric value between 0 and 1.")
  }
  if (length(qstep) > 1) {
    warning("Parameter 'qstep' has length > 1 and oly the first element",
            " is used")
    qstep <- qstep[1]
  }
  if (!is.character(type)) {
     warning("Parameter 'type' must be a character indicating the interpolation",
             "method, 'linear' method will be used.")
     type <- 'linear'
  }
  if (length(type) > 1) {
    warning("Parameter 'type' has length > 1 and oly the first element",
            " is used")
    qstep <- type[1]
  }
  if (!any(type  %in% c('linear', 'tricube'))) {
    stop("Parameter 'type' is incorrectly defined and 'linear' method will",
          " be used.")
  } 
  qmaped <- Apply(list(exp, obs), target_dims = c('lat', 'lon'), 
                  fun = qmapcor, wetday = wetday, qstep = qstep,
                  type = type)$output1
  return(qmaped)
}
#exp <- 1:10
#obs <- 1:20
qmapcor <- function(exp, obs, wetday = TRUE, qstep = 0.1, type = 'linear') {
  adjust <- fitQmapQUANT(obs, exp, wetday = wetday, qstep = qstep, type = type) 
  applied <- doQmapQUANT(exp, adjust, type = type)	
  return(applied)
}




