#'Compute the square-root of the cosine of the latitude weighting on the given 
#'array.
#'
#'This function performs square-root of the cosine of the latitude weighting on 
#'the given array.
#'
#'@param data A numeric array with named dimensions, representing the data to be
#'  applied the weights. It should have at least the latitude dimension and it 
#'  can have more other dimensions.
#'@param lat A numeric array with one dimension containing the latitudes.
#'@param lat_dim A character string indicating the name of the latitudinal
#'  dimension. The default value is 'lat'.
#'@param ncores An integer indicating the number of cores to use for parallel 
#'  computation. The default value is NULL.
#'
#'@return An array with same dimensions as parameter 'data'.
#'
#'@examples 
#'exp <- array(rnorm(1:30), dim = c(lat = 3, lon = 5, sdate = 2))
#'lat <- rnorm(3)*10
#'\dontrun{
#'res <- WeightCells(data = exp, lat = lat)
#'}
#'@import multiApply
#'@export
WeightCells <- function(data, lat, lat_dim = 'lat', ncores = NULL) {
  
  # Check inputs
  ## data
  if (is.null(data)) {
    stop("Parameter 'data' cannot be NULL.")
  }
  if (!is.numeric(data)) {
    stop("Parameter 'data' must be a numeric array.")
  }
  if (is.null(dim(data))) {
    stop("Parameter 'data' must be at least latitude dimension.")
  }
  if(any(is.null(names(dim(data)))) | any(nchar(names(dim(data))) == 0)) {
    stop("Parameter 'data' must have dimension names.")
  }

  ## lat_dim
  if (!is.character(lat_dim) | length(lat_dim) > 1) {
    stop("Parameter 'lat_dim' must be a character string.")
  }
  if (!lat_dim %in% names(dim(data))) {
    stop("Parameter 'lat_dim' is not found in 'data'.")
  }

  ## lat
  if (is.null(lat)) {
    stop("Parameter 'lat' cannot be NULL.")
  }
  if (!is.numeric(lat)) {
    stop("Parameter 'lat' must be a numeric array.")
  }
  if (dim(data)[lat_dim] != length(lat)) {
    stop("Length of parameter 'lat' doesn't match the length of ",
         "latitudinal dimension in parameter 'data'.")
  }
  ## ncores
  if (!is.null(ncores)) {
    if (!is.numeric(ncores) | ncores %% 1 != 0 | ncores <= 0 |
      length(ncores) > 1) {
      stop("Parameter 'ncores' must be either NULL or a positive integer.")
    }
  }

  namedims <- names(dim(data))

  res <- Apply(data = data, 
               target_dims = c(lat_dim),  
               fun = .WeightCells, 
               lat = as.vector(lat),
               ncores = ncores)$output1
  res <- Reorder(res, namedims)

  return(res)
}

.WeightCells <- function(data, lat) {
  dim_data <- dim(data)
  wt <- sqrt(cos(lat * pi/180))
  data <- wt*data
  return(data)
}
