#'Computes Bias Corrected Climatologies
#'
#'This function computes only per-pair climatologies from the experimental 
#'and observational matrices output from \code{Load()}.
#'To compute plain climatologies from only experimental or observational 
#'data from \code{Load()}, the following code can be used:\cr 
#'\code{clim <- array(apply(obs_data, c(1, 4, 5, 6), mean),}\cr
#'\code{              dim = dim(obs_datta)[-c(2, 3)])}\cr
#'The function \code{Clim()} computes per-pair climatologies using one of the 
#'following methods:
#'\enumerate{
#'  \item{per-pair method (Garcia-Serrano and Doblas-Reyes, CD, 2012)}
#'  \item{Kharin method (Karin et al, GRL, 2012)}
#'  \item{Fuckar method (Fuckar et al, GRL, 2014)}
#'}
#'\code{Clim()} computes climatologies using the startdates covered by the 
#'whole experiments/observational data sets. The startdates not available for 
#'all the data (model and obs) are excluded when computing the climatologies.
#'
#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to 
#'  c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon).
#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to 
#'  c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon).
#'@param memb TRUE/FALSE (1 climatology for each member). Default = TRUE.
#'@param kharin TRUE/FALSE (if Kharin method is applied or not). 
#'  Default = FALSE.
#'@param NDV TRUE/FALSE (if Fuckar method is applied or not). Default = FALSE.
#'
#'@importFrom abind adrop
#'@return
#'\item{clim_exp}{Array with same dimensions as var_exp except the third 
#'  (starting dates) and, depending on the parameters, the second (members), 
#'  which disappear.}
#'\item{clim_obs}{Array with same dimensions as var_obs except the third 
#'  (starting dates) and, depending on the parameters, the second (members), 
#'  which disappear.}
#'@keywords datagen
#'@author History:\cr
#'  0.9 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr
#'  1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN
#'@examples
#'# Load sample data as in Load() example:
#'example(Load)
#'clim <- Clim(sampleData$mod, sampleData$obs)
#'  \donttest{
#'PlotClim(clim$clim_exp, clim$clim_obs, 
#'         toptitle = paste('sea surface temperature climatologies'), 
#'         ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), 
#'         listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps')
#'  }
#'@export
Clim2 <- function(exp, obs, memb = TRUE, method = 'clim',
                 sdate_dim = 'sdates', member_dim = 'member') {
     #check memb
     if (!is.logical(memb)) {
          stop("Parameter 'memb' must be logical.")
     }
     if (length(memb) > 1) {
          warning("Parameter 'memb' has length greater than 1 and only the ",
                  "first element will be used.")
          memb = memb[1]
     }
     #check method
     if (!is.character(method)) {
          stop("Parameter 'method' must be a character string indicating one",
               " of 'kharin', 'NDV' or 'clim' methods.")
     }
     if (length(method) > 1) {
          warning("Parameter 'method' has length greater than 1 and only the ",
                  "first element will be used.")
          method = method[1]
     }
    #check exp
    if (is.null(exp)) {
        stop("Parameter 'exp' cannot be NULL.")
    }

    if (is.vector(exp)) {
      dim(exp) <- c(length(exp)) 
        if (memb) {
            names(dim(exp)) <- 'member'
        } else {
            if (is.vector(obs)) {
                names(dim(exp)) <- 'Dim1'
            } else if (length(dim(obs)) == 1) {
                names(dim(exp)) <- names(dim(obs))
            } else {
                stop("Parameter 'exp' and 'obs' must be arrays with named",
                     " dimensions.")
            }
        }
    }
    exp_dims <- dim(exp)
  
    #check obs
    if (is.null(obs)) {
        stop("Parameter 'obs' cannot be NULL.")
    }
    if (is.vector(obs)) {
        dim(obs) <- c(length(obs))
        if (memb) {
            dim(obs) <- c(member = 1, Dim1 = length(obs)) 
        } else {
            if (length(dim(exp)) == 1) {
                names(dim(obs)) <- names(exp_dims)
            } else {
                stop("Parameter 'obs' must have dimension names.")
            }
        }
    }
    obs_dims <- dim(obs)
    if (is.null(names(obs_dims))) {
        stop("Parameter 'obs' must have dimension names.")
    }
    if (is.null(names(exp_dims))) {
        stop("Parameter 'exp' must have dimension names.")
    }
    obs_dimnames <- names(obs_dims)
    exp_dimnames <- names(exp_dims)
    if (is.null(sdate_dim)) {
        sdate_dim = 'sdates'
    }
    if (is.null(member_dim)) {
        member_dim = 'member'
    }
    if (!(any(obs_dimnames %in% sdate_dim) & any(exp_dimnames %in% sdate_dim))) {
        stop("Parameter 'obs' and 'exp' needs one dimension for start",
             " dates.")
    }
    if (memb) {
        if (any(obs_dimnames %in% member_dim)) {
            if (obs_dims[member_dim] == 1) {
                var_obs <- adrop(var_obs, drop = member_dim)
            }
        }
        clim <- Apply(list(exp, obs),
                      target_dims = sdate_dim,
                      fun = .Clim, method = method, na.rm = na.rm)
        clim$clim_obs <- Subset(clim$clim_obs, along = member_dim, indices = 1)
        dims_out_exp <- names(exp_dims[-which(exp_dimnames == sdate_dim)])
        dims_out_obs <- names(obs_dims[-which(obs_dimnames == sdate_dim)])
        reorder <- match(dims_out_exp, names(dim(clim$clim_exp)))
        clim$clim_exp <- aperm(clim$clim_exp, reorder)
        names(dim(clim$clim_exp)) <- dims_out_exp[reorder]
        reorder <- match(dims_out_obs, names(dim(clim$clim_obs)))
        clim$clim_obs <- aperm(clim$clim_obs, reorder)
        names(dim(clim$clim_obs)) <- dims_out_obs[reorder]
    } else {
        clim <- Apply(list(exp, obs), target_dims = c(member_dim, sdate_dim),
                            fun = .Clim, method = method, na.rm = na.rm)
    }
  invisible(clim)
}
.Clim <- function(exp, obs, method = "clim", na.rm = TRUE, sdate_dim = 'sdates') {
    if (method == "kharin") {
        tmp_obs <- Trend(var = obs, sdate_dim = sdate_dim, interval = 1, pldegree = 1,
                          conf = FALSE, siglev = 0.95)$trend
        tmp_exp <- Trend(var = exp, interval = 1, pldegree = 1, sdate_dim = sdate_dim,
                          conf = TRUE, siglev = 0.95)$trend
      #  exp2 <- tmp_exp[1] + tmp_exp[2] * exp 
      #trend_obs[, , jdate, , , , ] <- InsertDim(InsertDim(tmp_obs2[4, , , , ] + 
      #                                jdate * tmp_obs2[2, , , , ], 1, dimexp[1]),
      #                                2, dimexp[2])

    } else if (method == "NDV") {
        #nose aun
    } else if (method == "clim") {
        # does the mean along start dates:
        clim_exp <- mean(exp, na.rm = na.rm)
        clim_obs <- mean(obs, na.rm = na.rm)
    } else {
         stop("Parameter 'method' must be one of 'kharin', 'NDV' or 'clim'.")
    }
    return(list(clim_exp = clim_exp, clim_obs = clim_obs))
}
