library(s2dv)
library(rbenchmark)
library(compiler)
library(multiApply)

.Season <- cmpfun(s2dv:::.Season)
Season <- function(data, time_dim = 'ftime', monini, moninf, monsup, 
                   method = mean, na.rm = TRUE, 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))) {  #is vector
    dim(data) <- c(length(data))
    names(dim(data)) <- time_dim
  }
  if(any(is.null(names(dim(data))))| any(nchar(names(dim(data))) == 0)) {
    stop("Parameter 'data' must have dimension names.")
  }
  ## time_dim
  if (!is.character(time_dim) | length(time_dim) > 1) {
    stop("Parameter 'time_dim' must be a character string.")
  }
  if (!time_dim %in% names(dim(data))) {
    stop("Parameter 'time_dim' is not found in 'data' dimension.")
  }
  ## monini
  if (!is.numeric(monini)) {
    stop("Parameter 'monini' must be a positive integer between 1 and 12.")
  } else {
    if (monini %% 1 != 0 | monini < 1 | monini > 12 | length(monini) > 1) {
      stop("Parameter 'monini' must be a positive integer between 1 and 12.")
    }
  }
  ## moninf
  if (!is.numeric(moninf)) {
    stop("Parameter 'moninf' must be a positive integer between 1 and 12.")
  } else {
    if (moninf %% 1 != 0 | moninf < 1 | moninf > 12 | length(moninf) > 1) {
      stop("Parameter 'moninf' must be a positive integer between 1 and 12.")
    }
  }
  ## monsup
  if (!is.numeric(monsup)) {
    stop("Parameter 'monsup' must be a positive integer between 1 and 12.")
  } else {
    if (monsup %% 1 != 0 | monsup < 1 | monsup > 12 | length(monsup) > 1) {
      stop("Parameter 'monsup' must be a positive integer between 1 and 12.")
    }
  }
  ## method
  if (!is.function(method)) {
    stop("Parameter 'method' should be an existing R function, e.g., mean or sum.")
  }
  ## na.rm
  if (!is.logical(na.rm) | length(na.rm) > 1) {
    stop("Parameter 'na.rm' must be one logical value.")
  }
  ## ncores
  if (!is.null(ncores)) {
    if (!is.numeric(ncores) | ncores %% 1 != 0 | ncores < 0 |
      length(ncores) > 1) {
      stop("Parameter 'ncores' must be a positive integer.")
    }
  } 

  ###############################
  # Calculate Season

    # Correction need if monini is not January: 
    moninf <- moninf - monini + 1
    monsup <- monsup - monini + 1
    moninf <- ifelse(moninf <= 0, moninf + 12, moninf)
    monsup <- ifelse(monsup <= 0, monsup + 12, monsup)

    while (monsup < moninf) {
        monsup <- monsup + 12
    }

    res <- Apply(list(data), 
                 target_dims = time_dim, 
                 output_dims = time_dim,
                 fun = .Season, 
                 monini = monini, moninf = moninf, monsup = monsup,
                 method = method, na.rm = na.rm, ncores = ncores)$output1

    return(res)
}


Comp_Season <- cmpfun(s2dv::Season)
Comp_Season_s2dverification <- cmpfun(s2dverification::Season)
# Test:
enableJIT(0)
benchmark("s2dverification::Season" = {
            data <- CSTools::lonlat_data$exp$data

            res_Regression <- s2dverification::Season(data, monini = 11, moninf = 12,
                                                      monsup = 1)
          },
          "Comp_s2dverification::Season" = {
            data <- CSTools::lonlat_data$exp$data
            res_Season <- Comp_Season_s2dverification(data, monini = 11,
                                                moninf = 12, monsup = 1)
          },
          "s2dv::Season" = {
            data <- CSTools::lonlat_data$exp$data
            res_Season <- s2dv::Season(data, monini = 11, moninf = 12, monsup = 1)
          },
          "s2dv:_Comp_.Season" = {
            data <- CSTools::lonlat_data$obs$data
            res_Season <- Season(data, monini = 11, moninf = 12, monsup = 1)
          },
          "s2dv::Comp_Season" = {
            data <- CSTools::lonlat_data$exp$data
            res_Season <- Comp_Season(data, monini = 11, moninf = 12, monsup = 1)
          },

          replications = 10,
          columns = c("test", "replications", "elapsed",
                      "relative", "user.self", "sys.self"))


