##############################################
# dat
set.seed(1)
mod <- rnorm(2 * 3 * 4 * 5 * 6 * 7)
dim(mod) <- c(dataset = 2, member = 3, sdate = 4, ftime = 5, lat = 6, lon = 7)
set.seed(2)
obs <- rnorm(1 * 1 * 4 * 5 * 6 * 7)
dim(obs) <- c(dataset = 1, member = 1, sdate = 4, ftime = 5, lat = 6, lon = 7)
lon <- seq(0, 30, 5)
lat <- seq(0, 25, 5)
exp <- list(data = mod, lat = lat, lon = lon)
obs <- list(data = obs, lat = lat, lon = lon)
attr(exp, 'class') <- 's2dv_cube'
attr(obs, 'class') <- 's2dv_cube'

# dat1
exp1 <- exp
exp1$data <- NULL

# dat2
exp2 <- exp
exp2$data <- array(rnorm(2 * 3 * 4 * 5 * 6 * 7), dim = c(var = 2, member = 3, sdate = 4, ftime = 5, lat = 6, lon = 7))

obs2 <- obs
obs2$data <- array(rnorm(2 * 3 * 2 * 5 * 6 * 1), dim = c(member = 1, sdate = 2, ftime = 5, lat = 6, lon = 7))

# dat3
exp3 <- exp
obs3 <- obs
exp3$data <- array(rnorm(2 * 3 * 1 * 5 * 6 * 7), dim = c(dataset = 2, member = 3, sdate = 1, ftime = 5, lat = 6, lon = 7))
obs3$data <- array(rnorm(2 * 3 * 1 * 5 * 6 * 1), dim = c(dataset = 2, member = 1, sdate = 1, ftime = 5, lat = 6, lon = 7))

# dat4
set.seed(1)
mod4 <- rnorm(2 * 3 * 4 * 5 * 6 * 7)
dim(mod4) <- c(datasets = 2, members = 3, sdates = 4, ftimes = 5, lat = 6, lon = 7)
set.seed(2)
obs4 <- rnorm(1 * 1 * 4 * 5 * 6 * 7)
dim(obs4) <- c(datasets = 1, members = 1, sdates = 4, ftimes = 5, lat = 6, lon = 7)
lon <- seq(0, 30, 5)
lat <- seq(0, 25, 5)
exp4 <- list(data = mod4, lat = lat, lon = lon)
obs4 <- list(data = obs4, lat = lat, lon = lon)
attr(exp4, 'class') <- 's2dv_cube'
attr(obs4, 'class') <- 's2dv_cube'
##############################################

test_that("1. Input checks", {
  # s2dv_cube
  expect_error(
    CST_Anomaly(exp = 1, obs = 1),
    "Parameter 'exp' and 'obs' must be of the class 's2dv_cube', as output by CSTools::CST_Load."
  )
  # exp and obs
  expect_error(
    CST_Anomaly(exp = exp1, obs = exp1),
    "One of the parameter 'exp' or 'obs' cannot be NULL."
  )
  expect_error(
    CST_Anomaly(exp = exp2, obs = obs),
    "Parameter 'dat_dim' is not found in 'exp' dimensions."
  )
  # dim_anom
  expect_error(
    CST_Anomaly(exp = exp, obs = obs, dim_anom = 3),
    paste0("Parameter 'dim_anom' must be a character string.")
  )
  expect_error(
    CST_Anomaly(exp = exp3, obs = obs3),
    "The length of dimension 'dim_anom' in label 'data' of the parameter 'exp' and 'obs' must be greater than 1."
  )
  expect_error(
    CST_Anomaly(exp4, obs4),
    "Parameter 'dim_anom' is not found in 'exp' or in 'obs' dimension in element 'data'."
  )
  # cross and memb
  expect_error(
    CST_Anomaly(exp = exp, obs = obs, cross = 1),
    "Parameters 'cross' and 'memb' must be logical."
  )
  expect_error(
    CST_Anomaly(exp = exp, obs = obs, memb = 1),
    "Parameters 'cross' and 'memb' must be logical."
  )
  # memb_dim
  expect_error(
    CST_Anomaly(exp = exp, obs = obs, memb_dim = 1),
    "Parameter 'memb_dim' must be a character string."
  )
  # filter_span
  expect_warning(
    CST_Anomaly(exp = exp, obs = obs, filter_span = 'a'),
    "Paramater 'filter_span' is not numeric and any filter is being applied."
  )
  # dat_dim
  expect_error(
    CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = 1),
    "Parameter 'dat_dim' must be a character vector."
  )
  # ftime_dim
  expect_error(
    CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'), memb = FALSE, filter_span = 2)$exp$data[1,1,1,,1,1],
    "Parameter 'ftime_dim' is not found in 'exp' or in 'obs' dimension in element 'data'.",
  )
})

##############################################
test_that("2. Output checks: dat", {
  expect_equal(
    names(CST_Anomaly(exp, obs)),
    c("exp", "obs")
  )
  expect_equal(
    dim(CST_Anomaly(exp, obs)$exp$data),
    c(dataset = 2, member = 3, sdate = 4, ftime = 5, lat = 6, lon = 7)
  )
  expect_equal(
    CST_Anomaly(exp, obs)$exp$data[1,1,1,,1,1],
    c(-0.64169277, 0.04953107, -0.59168037, 0.42660289, -0.77391490),
    tolerance = 0.0001
  )
  expect_equal(
    CST_Anomaly(exp, obs)$obs$data[1,1,1,,1,1],
    c(-0.83326562, -0.21035806, 1.17320132, 0.09760576, 0.28872829),
    tolerance = 0.0001
  )
  expect_equal(
    CST_Anomaly(exp, obs, memb = FALSE)$exp$data[1,1,1,,1,1],
    c(-0.9385105, 0.5140613, -0.3985370, 0.2916146, -1.0413568),
    tolerance = 0.0001
  )
  expect_equal(
    CST_Anomaly(exp, obs, memb = FALSE, filter_span = 2)$exp$data[1,1,1,,1,1],
    c(-0.8645582, 0.3478374, -0.3914569, 0.4555659, -1.1119619),
    tolerance = 0.0001
  )
})
##############################################
test_that("3. Output checks: dat4", {
  
  expect_equal(
    names(CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'))),
    c('exp', 'obs')
  )
  expect_equal(
    dim(CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'))$exp$data),
    c(datasets = 2, members = 3, sdates = 4, ftimes = 5, lat = 6, lon = 7)
  )
  expect_equal(
    CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'))$exp$data[1,1,1,,1,1],
    c(-0.64169277, 0.04953107, -0.59168037, 0.42660289, -0.77391490),
    tolerance = 0.0001
  )
  expect_equal(
    CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'))$obs$data[1,1,1,,1,1],
    c(-0.83326562, -0.21035806, 1.17320132, 0.09760576, 0.28872829),
    tolerance = 0.0001
  )
  expect_equal(
    CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'), memb = FALSE)$exp$data[1,1,1,,1,1],
    c(-0.9385105, 0.5140613, -0.3985370, 0.2916146, -1.0413568),
    tolerance = 0.0001
  )
  
  expect_equal(
    CST_Anomaly(exp4, obs4, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'), ftime_dim = 'ftimes', memb = FALSE, filter_span = 2)$exp$data[1,1,1,,1,1],
    c(-0.8645582, 0.3478374, -0.3914569, 0.4555659, -1.1119619),
    tolerance = 0.0001
  )
})