context("CSTools::CST_MultivarRMSE tests")

# dat1
set.seed(1)
mod1 <- abs(rnorm(1 * 3 * 4 * 5 * 6 * 7))
set.seed(2)
mod2 <- abs(rnorm(1 * 3 * 4 * 5 * 6 * 7))
dim(mod1) <- c(datasets = 1, members = 3, sdates = 4, ftimes = 5, lat = 6, lon = 7)
dim(mod2) <- c(datasets = 1, members = 3, sdates = 4, ftimes = 5, lat = 6, lon = 7)
set.seed(1)
obs1 <- abs(rnorm(1 * 1 * 4 * 5 * 6 * 7))
set.seed(2)
obs2 <- abs(rnorm(1 * 1 * 4 * 5 * 6 * 7))
dim(obs1) <- c(datasets = 1, members= 1, sdates = 4, ftimes = 5, lat = 6, lon = 7)
dim(obs2) <- c(datasets = 1, members = 1, sdates = 4, ftimes = 5, lat = 6, lon = 7)
lon <- seq(0, 30, 5)
lat <- seq(0, 25, 5)
coords <- list(lat = lat, lon = lon)

exp1 <- list(data = mod1, coords = coords, 
             attrs = list(Datasets = "EXP1", source_files = "file1", 
                          Variable = list('pre')))
exp2 <- list(data = mod2, coords = coords, 
             attrs = list(Datasets = "EXP2", source_files = "file2", 
                          Variable = list('tas')))
obs1_1 <- list(data = obs1, coords = coords, 
             attrs = list(Datasets = "OBS1", source_files = "file1", 
                          Variable = list('pre')))
obs2_1 <- list(data = obs2, coords = coords, 
             attrs = list(Datasets = "OBS2", source_files = "file2", 
                          Variable = list('tas')))

attr(exp1, 'class') <- 's2dv_cube'
attr(exp2, 'class') <- 's2dv_cube'
attr(obs1_1, 'class') <- 's2dv_cube'
attr(obs2_1, 'class') <- 's2dv_cube'

anom1 <- CST_Anomaly(exp1, obs1_1, cross = TRUE, memb = TRUE, dim_anom = 'sdates', memb_dim = 'members',dat_dim = c('datasets', 'members'))
anom2 <- CST_Anomaly(exp2, obs2_1, cross = TRUE, memb = TRUE, dim_anom = 'sdates', memb_dim = 'members', dat_dim = c('datasets', 'members'))

ano_exp <- list(anom1$exp, anom2$exp)
ano_obs <- list(anom1$obs, anom2$obs)

# dat2

dim(mod1) <- c(dataset = 1, member = 3, sdate = 4, ftime = 5, lat = 6, lon = 7)
dim(mod2) <- c(dataset = 1, member = 3, sdate = 4, ftime = 5, lat = 6, lon = 7)
dim(obs1) <- c(dataset = 1, member = 1, sdate = 4, ftime = 5, lat = 6, lon = 7)
dim(obs2) <- c(dataset = 1, member = 1, sdate = 4, ftime = 5, lat = 6, lon = 7)

exp1 <- list(data = mod1, coords = coords, 
             attrs = list(Datasets = "EXP1", source_files = "file1", 
                          Variable = list('pre')))
exp2 <- list(data = mod2, coords = coords, 
             attrs = list(Datasets = "EXP2", source_files = "file2", 
                          Variable = list('tas')))
obs1 <- list(data = obs1, coords = coords, 
             attrs = list(Datasets = "OBS1", source_files = "file1", 
                          Variable = list('pre')))
obs2 <- list(data = obs2, coords = coords, 
             attrs = list(Datasets = "OBS2", source_files = "file2", 
                          Variable = list('tas')))

attr(exp1, 'class') <- 's2dv_cube'
attr(exp2, 'class') <- 's2dv_cube'
attr(obs1, 'class') <- 's2dv_cube'
attr(obs2, 'class') <- 's2dv_cube'

anom1 <- CST_Anomaly(exp1, obs1, cross = TRUE, memb = TRUE)
anom2 <- CST_Anomaly(exp2, obs2, cross = TRUE, memb = TRUE)

ano_exp2 <- list(anom1$exp, anom2$exp)
ano_obs2 <- list(anom1$obs, anom2$obs)

##############################################
test_that("1. Input checks", {
  # s2dv_cube
  expect_error(
    CST_MultivarRMSE(exp = 1, obs = 1),
    "Parameters 'exp' and 'obs' must be lists of 's2dv_cube' objects"
  )
  # exp and obs
  expect_error(
    CST_MultivarRMSE(exp = exp1, obs = exp1),
    paste0("Elements of the list in parameter 'exp' must be of the class ",
           "'s2dv_cube', as output by CSTools::CST_Load.")
  )
  # exp and obs
  expect_error(
    CST_MultivarRMSE(exp = c(ano_exp,ano_exp), obs = ano_obs),
    "Parameters 'exp' and 'obs' must be of the same length."
  )
  # memb_dim
  expect_error(
    CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, memb_dim = NULL),
    "Parameter 'memb_dim' cannot be NULL."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, memb_dim = 1),
    "Parameter 'memb_dim' must be a character string."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs),
    "Dimension names of element 'data' from parameters 'exp' and 'obs' should be equal."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, memb_dim = 'memb'),
    "Parameter 'memb_dim' is not found in 'exp' or in 'obs' dimension."
  )
  # dat_dim
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, dat_dim = 1),
    "Parameter 'dat_dim' must be a character string."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, dat_dim = 'dats'),
    "Parameter 'dat_dim' is not found in 'exp' or in 'obs' dimension."
  )
  # ftime_dim
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, ftime_dim = 1),
    "Parameter 'ftime_dim' must be a character string."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, ftime_dim = 'ftimes'),
    "Parameter 'ftime_dim' is not found in 'exp' or in 'obs' dimension."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, ftime_dim = NULL),
    "Parameter 'ftime_dim' cannot be NULL."
  )
  # sdate_dim
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, sdate_dim = 1),
    "Parameter 'sdate_dim' must be a character string."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, sdate_dim = 'sdates'),
    "Parameter 'sdate_dim' is not found in 'exp' or in 'obs' dimension."
  )
  expect_error(
    CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, sdate_dim = NULL),
    "Parameter 'sdate_dim' cannot be NULL."
  )
})

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

test_that("2. Output checks", {
  res1 <- CST_MultivarRMSE(exp = ano_exp2, obs = ano_obs2, weight = c(1, 2))
  res2 <- CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, weight = c(1, 2), 
                           dat_dim = 'datasets', ftime_dim = 'ftimes', 
                           memb_dim = 'members', sdate_dim = 'sdates')
  # res3 <- CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, weight = c(1, 2), 
  #                          dat_dim = NULL, ftime_dim = 'ftimes', 
  #                          memb_dim = 'members', sdate_dim = 'sdates')
  expect_equal(
    names(res1),
    c('data', 'coords', 'attrs')
  )
  expect_equal(
    dim(res1$data),
    dim(res2$data)
  )
  expect_equal(
    dim(res1$data),
    c(nexp = 1, nobs = 1, lat = 6, lon = 7)
  )
  expect_equal(
    res1$data,
    res2$data
  )
  expect_equal(
    as.vector(res1$data)[1:5],
    c(0.9184747, 1.0452328, 1.7559577, 0.7936543, 0.9163216), 
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(res2$data)[1:5],
    c(0.9184747, 1.0452328, 1.7559577, 0.7936543, 0.9163216), 
    tolerance = 0.0001
  )
  # expect_equal(
  #   dim(res3$data),
  #   c(datasets = 1, lat = 6, lon = 7)
  # )
  # expect_equal(
  #   as.vector(res3$data)[1:5],
  #   c(0.9184747, 1.0452328, 1.7559577, 0.7936543, 0.9163216), 
  #   tolerance = 0.0001
  # )
})
