#'@rdname CST_Analogs
#'@title Downscaling using Analogs based on large scale fields.
#' 
#'@author M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it}
#'@author Maria M. Chaves-Montero, \email{mariadm.chaves@cmcc.it }
#'@author Nuria Perez-Zanon \email{nuria.perez@bsc.es}
#'
#'@description This function perform a downscaling using Analogs. To compute 
#'the analogs, the function search for days with similar large scale conditions
#'to downscaled fields to a local scale. The large scale and the local scale 
#'regions are defined by the user. The large scale is usually given by 
#'atmospheric circulation as sea level pressure or geopotential height 
#'(Yiou et al, 2013) but the function gives the possibility to use another 
#'field. The local scale will be usually given by precipitation or temperature 
#'fields, but might be another variable.The analogs function will find the best
#'analogs based in Minimum Euclidean distance in the large scale pattern
#'(i.e.SLP).
#'
#'The search of analogs must be done in the longest dataset posible. This is 
#'important since it is necessary to have a good representation of the 
#'possible states of the field in the past, and therefore, to get better 
#'analogs. 
#'This function has not constrains of specific regions, variables to downscale,
#'or data to be used (seasonal forecast data, climate projections data, 
#'reanalyses data). The regrid into a finner scale is done interpolating with 
#'CST_Load. Then, this interpolation is corrected selecting the analogs in the 
#'large and local scale in based of the observations. The function is an 
#'adapted version of the method of Yiou et al 2013. For an advanced search of 
#'Analogs (multiple Analogs, different criterias, further information from the
#'metrics and date of the selected Analogs) use the'Analog'
#'function within 'CSTools' package.   
#'
#'@references Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard,
#' and M. Vrac, 2013 : Ensemble reconstruction of the atmospheric column 
#' from surface pressure using analogues.  Clim. Dyn., 41, 1419-1437. 
#' \email{pascal.yiou@lsce.ipsl.fr}
#'
#'@param expL an 's2dv_cube' object containing the experimental field on the 
#'large scale for which the analog is aimed. This field is used to in all the
#'criterias. If parameter 'expVar' is not provided, the function will return 
#'the expL analog. The element 'data' in the 's2dv_cube' object must have, at
#'least, latitudinal and longitudinal dimensions. The object is expect to be 
#'already subset for the desired large scale region.
#'@param obsL an 's2dv_cube' object containing the observational field on the
#'large scale. The element 'data' in the 's2dv_cube' object must have the same 
#'latitudinal and longitudinal dimensions as parameter 'expL' and a temporal 
#'dimension with the maximum number of available observations.
#'@param time_obsL a character string indicating the date of the observations 
#'in the date format (i.e. "yyyy-mm-dd")
#'@param time_expL a character string indicating the date of the experiment 
#'in the same format than time_obsL (i.e. "yyyy-mm-dd")
#'@param expVar an 's2dv_cube' object containing the experimental field on the
#'local scale, usually a different variable to the parameter 'expL'. If it is 
#'not NULL (by default, NULL), the returned field by this function will be the 
#'analog of parameter 'expVar'.
#'@param obsVar an 's2dv_cube' containing the field of the same variable as the 
#'passed in parameter 'expVar' for the same region.
#'@param region a vector of length four indicating the minimum longitude, the 
#'maximum longitude, the minimum latitude and the maximum latitude.
#'@param dimension the dimension where the downscaling will be performed (i.e.
#''member', 'sdate',etc))
#'
#'@import multiApply
#'@import s2dverification
#'@import abind
#'@import ClimProjDiags
#'
#'@seealso code{\link{CST_Load}}, \code{\link[s2dverification]{Load}} and 
#'\code{\link[s2dverification]{CDORemap}}
#'
#'@return An 'array' object containing the dowscaled values of the best 
#'analogs. 
#'@examples
#'# using lonlat_data.RData in "~/cstools/data/lonlat_data.RData"
#'expL = lonlat_data$exp$data
#'obsL = lonlat_data$obs$data
#'lon = as.vector(lonlat_data$exp$lon)
#'lat = as.vector(lonlat_data$exp$lat)
#'time_expL=lonlat_data$exp$Dates$start[1]
#'# corresponding to stdate 1 and ftime 1 
#'sdate=1
#'ftime=1
#'time_obsL=lonlat_data$obs$Dates$start
#'region=c(min(lon),max(lon),min(lat),max(lat))
#'# to select the first timestep (stdate=1, ftime=1) and compute the downscaling
#'# in all the members
#'expL=expL[1,,sdate,ftime,,] 
#'obsL=obsL[1,1,,,,] 
#'dimension=names(dim(expL))[1]
#'dim(obsL) <-c(dim(obsL)[1]*dim(obsL)[2], dim(obsL)[3], dim(obsL)[4])
#'names(dim(obsL))[1] <- 'time'
#'downscaled_field<- CST_Analogs(expL = expL, obsL = obsL, time_obsL=time_obsL,
#'                               time_expL=time_expL,dimension=dimension,
#'                               expVar = expL, obsVar = obsL, 
#'                               lonVar = lon, 
#'                               latVar = lat, region = region)
#'

CST_Analogs <- function(expL, obsL, time_obsL, time_expL, dimension,
                expVar = NULL, obsVar = NULL, region = NULL, 
                lonVar=NULL, latVar=NULL){

  if (is.null(dimension)) {
    stop("It is necessary to choose a dimension to perform the downscaling
         (i.e. 'member', 'ftime','stdate') ")
  }else{
    warning(paste0("the dimension selected to perform the downscaling is '",
                   dimension,"' "))
  }
  ApplyAnalog<-Apply(expL, target_dims = list(c('lat', 'lon')),
                     margins=dimension,
                     fun = Analogs, 
                     obsL = obsL, time_obsL=time_obsL, 
                     criteria = "Large_dist", lonVar = lon,time_expL=time_expL,
                     latVar = lat, region = region)
  result<-ApplyAnalog$output1[1,,,]
  return(result)
  
}