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

# dat
var_exp <- array(1:6, dim = c(sdate = 2, member = 3))
var_exp <- list(data = var_exp)
class(var_exp) <- 's2dv_cube' 
aweights <- c(0.2, 0.1, 0.3, 0.4, 0.5, 0.5)
dim(aweights) <- c(sdate = 2, member = 3)
terciles <- rep(c(35, 45))
dim(terciles) <- c(tercil = 2)

# dat1
var_exp1 <- array(1:6, dim = c(time = 2, member = 3))
aweights1 <- c(0.2, 0.1, 0.3, 0.4, 0.5, 0.5)
dim(aweights1) <- c(time = 2, member = 3)

# dat2
var_exp2 <- array(1:(2*4*3*2), dim = c(time = 2, member = 4, lat = 3, lon = 2))
aweights2 <- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.4, 0.3, 
              0.1, 0.2, 0.4, 0.4, 0.1, 0.2, 0.4, 0.2)
dim(aweights2) <- c(time = 2, member = 4, dataset = 2)
var_exp2 <- list(data = var_exp2)
class(var_exp2) <- 's2dv_cube'
terciles2 <- rep(c(35, 45), 3*2)
dim(terciles2) <- c(tercil = 2, lat = 3, lon = 2)

result2 <- array(c(4.4, 5.4, 12.4, 13.4, 20.4, 21.4,
                  28.4, 29.4, 36.4, 37.4, 44.4, 45.4,
                  4.6, 4.8, 12.6, 12.8, 20.6, 20.8,
                  28.6, 28.8, 36.6, 36.8, 44.6, 44.8), 
                 dim = c(time = 2, lat = 3, lon = 2, dataset = 2))

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

test_that("1. Input checks", {
  # s2dv_cube
  expect_error(
    CST_BEI_Weighting(var_exp = 1, aweights = 1, type = 'probs', time_dim_name = 1),
    paste0("Parameter 'var_exp' must be of the class 's2dv_cube', ",
           "as output by CSTools::CST_Load.")
  )
  # type
  expect_error(
    CST_BEI_Weighting(var_exp = var_exp, aweights = aweights, type = 1, 
                      time_dim_name = 1),
    paste0("Parameter 'type' must be a character string, 'probs' or ",
           "'ensembleMean', indicating the type of output.")
  )
  expect_error(
    CST_BEI_Weighting(var_exp = var_exp, aweights = aweights, type = c('a'), 
                      time_dim_name = 1),
    paste0("Parameter 'type' must be a character string ('probs' or ",
           "'ensembleMean'), indicating the type of output."),
    fixed = TRUE
  )
  # var_exp
  expect_error(
    BEI_EMWeighting(var_exp = 1, aweights = 2),
    "Parameter 'var_exp' must be an array."
  )
  expect_error(
    BEI_ProbsWeighting(var_exp = 1, aweights = 2),
    "Parameter 'var_exp' must be an array."
  )
  # aweights
  expect_error(
    BEI_EMWeighting(var_exp = var_exp$data, aweights = 2),
    "Parameter 'aweights' must be an array."
  )
  # aweights
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = 2),
    "Parameter 'aweights' must be an array."
  )
  # terciles
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = aweights, terciles = NULL),
    "Parameter 'terciles' cannot be null."
  )
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = aweights, 
                       terciles = 1),
    "Parameter 'terciles' must be an array."
  )
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = aweights, 
                       terciles = array(1:10, c(10))),
    "Parameter 'terciles' should have dimension names."
  )
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = aweights, 
                       terciles = array(1:10, c(time = 10))),
    "Parameter 'terciles' must have dimension 'tercil'."
  )
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = aweights, 
                       terciles = array(1:10, c(tercil = 10))),
    paste0("Length of dimension 'tercil' ",
           "of parameter 'terciles' must be equal to 2.")
  )
  # time_dim_name
  expect_error(
    BEI_EMWeighting(var_exp = var_exp$data, aweights = aweights, time_dim_name = 1),
    paste0("Parameter 'time_dim_name' must be a character string indicating",
           " the name of the temporal dimension.")
  )
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = aweights, 
                       terciles = terciles, time_dim_name = 1),
    paste0("Parameter 'time_dim_name' must be a character string indicating",
           " the name of the temporal dimension.")
  )
  # memb_dim
  expect_error(
    BEI_EMWeighting(var_exp = var_exp$data, aweights = aweights, memb_dim = 1),
    paste0("Parameter 'memb_dim' must be a character string indicating",
           " the name of the member dimension.")
  )
  expect_error(
    BEI_ProbsWeighting(var_exp = var_exp$data, aweights = aweights, 
                       terciles = terciles, memb_dim = 1),
    paste0("Parameter 'memb_dim' must be a character string indicating",
           " the name of the member dimension.")
  )
  # var_exp, aweights (2)
  expect_error(
    BEI_EMWeighting(var_exp = array(10), aweights = array(10)),
    "Parameters 'var_exp' and 'aweights' should have dimension names."
  )
  expect_error(
    BEI_EMWeighting(var_exp = var_exp$data, aweights = aweights),
    "Parameter 'var_exp' must have temporal dimension."
  )
  expect_error(
    BEI_EMWeighting(var_exp = var_exp1, aweights = aweights),
    "Parameter 'aweights' must have temporal dimension."
  )
  expect_error(
    BEI_EMWeighting(var_exp = array(1:6, dim = c(time = 2, members = 3)), 
                    aweights = aweights1),
    "Parameter 'var_exp' must have member dimension."
  )
  expect_error(
    BEI_EMWeighting(var_exp = var_exp1, 
                    aweights = array(1:6, dim = c(time = 2, members = 3))),
    "Parameter 'aweights' must have member dimension."
  )
  expect_error(
    BEI_EMWeighting(var_exp =  array(1:6, dim = c(time = 1, member = 3)), 
                    aweights = array(1:6, dim = c(time = 2, member = 3))),
    paste0("Length of temporal dimension ",
           "of parameter 'var_exp' and 'aweights' must be equal.")
  )
  expect_error(
    BEI_EMWeighting(var_exp =  array(1:6, dim = c(time = 2, member = 2)), 
                    aweights = array(1:6, dim = c(time = 2, member = 3))),
    paste0("Length of member dimension ",
           "of parameter 'var_exp' and 'aweights' must be equal.")
  )
})  

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

test_that("basic use case", {
  expect_equal(
    CST_BEI_Weighting(var_exp2, aweights2, type = 'ensembleMean')$data, 
    result2, 
    tolerance = 1e-4
  )
  expect_equal(
    as.vector(CST_BEI_Weighting(var_exp2, aweights2)$data[, , 2, 2]), 
    c(28.6, 28.8, 36.6, 36.8, 44.6, 44.8),
    tolerance = 1e-4
  )
  res <- CST_BEI_Weighting(var_exp2, aweights2, type = 'probs', 
                           terciles = terciles2)$data
  expect_equal(
    dim(res), 
    c(time = 2, tercil = 3, lat = 3, lon = 2, dataset = 2), 
    tolerance = 1e-4
  )
  expect_equal(
    res[, , 2, 2, 2], 
    array(c(0.5, 0.2, 0.5, 0.8, 0, 0), dim = c(time = 2, tercil = 3)), 
    tolerance = 1e-4
  )
  expect_equal(
    BEI_EMWeighting(var_exp =  array(1:6, dim = c(times = 2, members = 3)), 
                    aweights = array(1:6, dim = c(times = 2, members = 3)),
                    time_dim_name = 'times', memb_dim = 'members'), 
    array(c(35, 56), dim = c(times = 2)), 
    tolerance = 1e-4
  )
})

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