
library(CSTools)

# dat1
threshold <- 26
dat1 <- array(abs(rnorm(5 * 3 * 214 * 2)*50),
                  c(member = 5, sdate = 3, time = 214, lon = 2)) 
dates0 <- c(seq(as.Date("01-05-2000", format = "%d-%m-%Y"), 
                as.Date("30-11-2000", format = "%d-%m-%Y"), by = 'day'),
            seq(as.Date("01-05-2001", format = "%d-%m-%Y"), 
                as.Date("30-11-2001", format = "%d-%m-%Y"), by = 'day'),
            seq(as.Date("01-05-2002", format = "%d-%m-%Y"), 
                as.Date("30-11-2002", format = "%d-%m-%Y"), by = 'day'))
dates1 <- dates0
dim(dates1) <- c(sdate = 3, time = 214)

##############################################
test_that("1. Sanity checks", {
  expect_error(
    QThreshold(NULL),
    "Parameter 'data' cannot be NULL."
  )
  expect_error(
    QThreshold('x'),
    "Parameter 'data' must be numeric."
  )
  data <- 1:20
  expect_error(
    QThreshold(data, NULL),
    "Parameter 'threshold' cannot be NULL."
  )
  expect_error(
    QThreshold(data, 'x'),
    "Parameter 'threshold' must be numeric."
  )
  threshold <- 10
  expect_error(
    QThreshold(data, threshold),
    "'x' must have 1 or more non-missing values"
  )
  dim(data) <- c(2, 10)
  expect_error(
    QThreshold(data, threshold),
    "Parameter 'data' must have named dimensions."
  )
  names(dim(data)) <- c('lat', 'sdate')
  threshold <- array(1:2, 2)
  expect_error(
    QThreshold(data, threshold),
    "Parameter 'threshold' must have named dimensions."
  )
  dim(threshold) <- c(time = 2)
  data <- array(1:40, c(x = 2, sdate = 20))
  threshold <- 10
  expect_equal(
    dim(QThreshold(data, threshold)), 
    c(sdate = 20, x = 2)
  )
  data <- array(1:40, c(x = 2, time = 20))
  expect_error(
    QThreshold(data, threshold),
    "Could not find dimension 'sdate' in 1th object provided in 'data'."
  )
  expect_equal(
    dim(QThreshold(data, threshold, sdate_dim = 'time')),
    c(time = 20, x = 2)
  )
  dim(threshold) <- c(member = 1, time = 1)
  expect_equal(
    dim(QThreshold(data, threshold, sdate_dim = 'time')),
    c(time = 20, x = 2)
  )
  expect_equal(
    dim(QThreshold(data, threshold, memb_dim = 'x', sdate_dim = 'time')),
    c(time = 20, x = 2)
  )
  expect_error(
    QThreshold(data, threshold, sdate_dim = 'x', ncores = 'Z'),
    "Parameter 'ncores' must be numeric"
  )

  # dimensions:
  data <- array(1:20, c(time = 5, sdate = 2, lat = 2))
  # does this case made sense?
  threshold <- array(1:5, c(time = 5))  
  expect_equal(
    dim(QThreshold(data, threshold)),
    c(sdate = 2, time = 5, lat = 2)
  )
  threshold <- array(1:2, c(lat = 2))
  expect_equal(
    dim(QThreshold(data, threshold)),
    c(sdate = 2, time = 5, lat = 2)
  )
  data <- array(1:60, c(time = 5, member = 3, sdate = 2, lat = 2))
  expect_equal(
    dim(QThreshold(data, threshold)),
    c(sdate = 2, member = 3, time = 5, lat = 2)
  )
  expect_equal(
    dim(QThreshold(data, threshold, memb_dim = NULL)),
    c(sdate = 2, time = 5, member = 3, lat = 2)
  )

  # test different common dimensions
  
  exp <- array(1:61, dim = c(time = 61, sdate = 3))
  threshold <- array(1:61, dim = c(time = 61))
  Dates <- c(seq(as.Date("01-05-2000", format = "%d-%m-%Y"), 
                as.Date("30-06-2000", format = "%d-%m-%Y"), by = 'day'),
            seq(as.Date("01-05-2001", format = "%d-%m-%Y"), 
                as.Date("30-06-2001", format = "%d-%m-%Y"), by = 'day'),
            seq(as.Date("01-05-2002", format = "%d-%m-%Y"), 
                as.Date("30-06-2002", format = "%d-%m-%Y"), by = 'day'))
  dim(Dates) <- c(time = 61, sdate = 3, syear = 1)
  res <- QThreshold(data = exp, dates = Dates, 
                    start = list(21, 4), end = list(21, 6), threshold = threshold, 
                    time_dim = 'time', sdate_dim = 'sdate')
  expect_equal(
    dim(res),
    c(sdate = 3, time = 52)
  )
  # test start and end
  expect_warning(
    QThreshold(dat1, threshold = 26, dates = dates0, start = list(21, 4), 
               end = list(21, 6)),
    paste0("Parameter 'dates' must have named dimensions if 'start' and ",
           "'end' are not NULL. All data will be used.")
  )
  expect_equal(
    dim(QThreshold(dat1, threshold = 26, dates = dates1, start = list(21, 4), 
                   end = list(21, 6))),
    c(sdate = 3, member = 5, time = 52, lon = 2)
  )
  # start and end when dates is not provided
  expect_warning(
    QThreshold(array(1:61, dim = c(time = 61, sdate = 3)), threshold = 25,
               start = list(05, 02), end = list(05, 09)),
    paste0("Parameter 'dates' is NULL and the average of the full data ", 
           "provided in 'data' is computed.")
  )
})

##############################################

test_that("2. Seasonal forecasts", {
  obs <- CSTools::lonlat_temp$obs$data - 248
  obs_percentile <- QThreshold(obs, threshold = 35)
  expect_equal(
    dim(obs)[4:6], 
    dim(obs_percentile)[4:6]
  )
  expect_equal(
    obs_percentile[, 1, 1, 3, 20, 53], 
    c(rep(0.4, 4), rep(0.2, 2))
  )
  obs1 <- obs[,,2,,,] # no sdate
  expect_error(
    obs1_percentile <- QThreshold(obs1, threshold = 35),
    "Could not find dimension 'sdate' in 1th object provided in 'data'."
  )
  obs1 <- s2dv::InsertDim(obs1, 1, 1, name = 'sdate') # one sdate
  expect_error(
    obs1_percentile <- QThreshold(obs1, threshold = 35),
    "'x' must have 1 or more non-missing values"
  )
  obs2 <- obs[,,,2,,] # one time
  obs2_percentile <- QThreshold(obs2, threshold = 35)
  expect_equal(
    dim(obs2), 
    dim(obs2_percentile)
  )
  expect_equal(
    obs2_percentile[,14,53], 
    c(0.6, 0.4, 0.6, 0.6, 0.4, 0.4)
  )
})

##############################################
