#' @title Computes Anomalies 
#' @description This function computes anomalies from any model or observational data 
#' @param var Array with model or observational data. Must be an array of dimensions: (nmembers,nt,nlon,nlat), 
#' (nt,nlon,nlat), (nt,nlat,nlon), (nt,ns) or (nt) 
#' @param crossValid Boolean (TRUE: doing crossValid; FALSE: not doing crossValid)
#' @return Array with same dimensions as 'var'
#' @author Sanchez-Garcia,E. \email{esanchezg@aemet.es}  
#' @example 
#' data <- 1:10
#' dim(data)
#' length(data)
#' out <- AnomaliesVar(var = data)
#' dim(out)
#' length(out)
#' out <- AnomaliesVar(var = data, crossValid = TRUE)
#' dim(out)
#' length(out)
#' @export  
AnomaliesVar <- function(var, crossValid=FALSE) {
  
  dimvar <- dim(var)
  
  if((is.null(dimvar) & length(var) > 1) | length(dimvar) == 1){
    nt <- length(var)
    anomVar <- array(dim = length(var))
    if (crossValid) {
      # Generating anomalies with cross-validation technique
      for (itime in 1:nt){
        clim <- mean(var[-itime], na.rm = TRUE)
        anomVar[itime] <- var[itime] - clim
      }
      return(anomVar)
    } else {
      # Generating anomalies without cross-validation technique
      clim <- mean(var, na.rm = TRUE)
      anomVar <- var - clim
      return(anomVar)
    }  
  } else if(length(dimvar) == 0 | length(dimvar) > 4){
    stop("Wrong dimensions")
  } else{
    if (length(dimvar) == 4){
      nmembers <- dimvar[1]
      nt <- dimvar[2]
      anomVar <- array(dim = dimvar)
      if (crossValid) {
        # Generating anomalies with cross-validation technique
        for (itime in 1:nt){
          tmp1 <- array(var[,itime,,],dim=dimvar[-2])
          tmp2 <- array(var[,-itime,,],dim = c(dimvar[1],dimvar[2]-1,dimvar[3:4]))
          clim <- array(apply(tmp2, c(3,4), mean, na.rm = TRUE), dim = dim(tmp2)[-c(1,2)])
          clim <- InsertDim(clim, 1, dimvar[1])
          anomVar[,itime,,] <- tmp1 - clim
        }
        return(anomVar)
      } else {
        # Generating anomalies without cross-validation technique
        clim <- array(apply(var, c(3, 4), mean, na.rm = TRUE), dim = dim(var)[-c(1,2)])
        clim <- InsertDim(InsertDim(clim, 1, dimvar[1]),2,dimvar[2])
        anomVar <- var - clim
        return(anomVar)
      } 
    }else if (length(dimvar) == 3){
      nt <- dimvar[1]
      anomVar <- array(dim = dimvar)
      if (crossValid) {
        # Generating anomalies with cross-validation technique
        for (itime in 1:nt){
          tmp1 <- array(var[itime,,],dim=dimvar[-1])
          tmp2 <- array(var[-itime,,],dim = c(dimvar[1]-1,dimvar[2:3]))
          clim <- array(apply(tmp2, c(2,3), mean, na.rm = TRUE), dim = dim(tmp2)[-c(1)])
          anomVar[itime,,] <- tmp1 - clim
        }
        return(anomVar)
      } else {
        # Generating anomalies without cross-validation technique
        clim <- array(apply(var, c(2, 3), mean, na.rm = TRUE), dim = dim(var)[-c(1)])
        clim <- InsertDim(clim, 1, dimvar[1])
        anomVar <- var - clim
        return(anomVar)
      }  
    } else if(length(dimvar) == 2){
      nt <- dimvar[1]
      ns <- dimvar[2]
      anomVar <- array(dim = dimvar)
      if (crossValid) {
        # Generating anomalies with cross-validation technique
        for (itime in 1:nt){
          tmp1 <- array(var[itime,],dim=dimvar[-1])
          tmp2 <- array(var[-itime,],dim = c(dimvar[1]-1,dimvar[2]))
          clim <- array(apply(tmp2, c(2), mean, na.rm = TRUE), dim = dim(tmp2)[-c(1)])
          anomVar[itime,] <- tmp1 - clim
        }
        return(anomVar)
      } else {
        # Generating anomalies without cross-validation technique
        clim <- array(apply(var, c(2), mean, na.rm = TRUE), dim = dim(var)[-c(1)])
        clim <- InsertDim(clim, 1, dimvar[1])
        anomVar <- var - clim
        return(anomVar)
      }  
    } 
  }
}




#'@title Converts an array of integers (period of months) to character 
#'@description This function converts an array of integers (period of months) 
#'to character 
#'@param monthsInteger Integer array with months 
#'@return Character with months initial character
#'@author Sanchez-Garcia,E. \email{esanchezg@aemet.es}  
#' @examples
#' monthsInteger <- c(11,12,1)
#' sMonths <- Months2string(monthsInteger)
#' str(sMonths) 
#'@export
Months2string <- function(monthsInteger) {
  if(!is.vector(monthsInteger) ){
    stop("Input wrong")
  }
  sMonths <- ""
  for (i in 1: length(monthsInteger)){
    sMonths <- paste(sMonths,substring(month.abb[monthsInteger[i]],1,1), sep="")
  }
  sMonths
}

MonthsToString <- function(numeric.months) { #vector de meses numérico rango de 1 a 12
  if (!is.vector(numeric.months)) {
    stop("Parameter 'numeric.months' must be a vector.")
  }
  paste(unlist(lapply(numeric.months, .MonthsToString)), collapse = "")
}
.MonthsToString <- function(x) { #x: es el número de un mes
  if (length(x) != 1) {
    stop("Parameter 'x' must be one single element.")
  }
  if (!is.numeric(x)) {
    stop("Parameter 'x' must be numeric.")
    if (x %% 1 != 0) { 
      stop("Parameter 'x' must be numeric integer.")
    }
  }
  substring(month.abb[x], 1, 1)
}
# Examples:
.MonthsToString(x = 11)
MonthsToString(numeric.months = c(11, 12, 1))
#Checks of checks
MonthsToString(numeric.months = "aadf") # correct error
MonthsToString(numeric.months = "a") # correct error
MonthsToString(numeric.months = 1) 
MonthsToString(numeric.months = 1 : 3)  
MonthsToString(numeric.months = list(1 : 3)) # correct error
MonthsToString(numeric.months = list(c(1 : 3))) # correct error
a <- 1 : 12
dim(a) <- c(2, 6)
MonthsToString(numeric.months = a) # correct error
dim(a) <- c(1, 12)
MonthsToString(numeric.months = a) # correct error
dim(a) <- c(12, 1)               
MonthsToString(numeric.months = a) # correct error
MonthsToString(numeric.months = 0.2) # correct error
is.integer(0.2)
