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

# dat1
set.seed(1)
exp1 <- array(rnorm(60), dim = c(member = 3, sdate = 10, lat = 2))
set.seed(2)
obs1 <- array(rnorm(20), dim = c(sdate = 10, lat = 2))
set.seed(3)
ref1 <- array(rnorm(40), dim = c(member = 2, sdate = 10, lat = 2))

# dat2
set.seed(1)
exp2 <- array(rnorm(20), dim = c(member = 2, sdate = 10))
set.seed(2)
obs2 <- array(rnorm(10), dim = c(sdate = 10))
set.seed(3)
ref2 <- array(rnorm(20), dim = c(member = 2, sdate = 10))

# dat2_2
set.seed(1)
exp2_2 <- array(rnorm(20), dim = c(member = 2, sdate = 10, dataset = 1))
set.seed(2)
obs2_2 <- array(rnorm(10), dim = c(sdate = 10, dataset = 1))
set.seed(3)
ref2_2 <- array(rnorm(20), dim = c(member = 2, sdate = 10, dataset = 1))

# dat3
set.seed(1)
exp3 <- array(rnorm(60), dim = c(member = 2, sdate = 10, dataset = 3))
set.seed(2)
obs3 <- array(rnorm(20), dim = c(member = 1, sdate = 10, dataset = 2))
set.seed(3)
ref3 <- array(rnorm(60), dim = c(member = 2, sdate = 10, dataset = 3))

# dat4
set.seed(1)
exp4 <- array(rnorm(60), dim = c(member = 2, sdate = 10, dataset = 3, lat = 2))
set.seed(2)
obs4 <- array(rnorm(20), dim = c(member = 1, sdate = 10, dataset = 2, lat = 2))
set.seed(3)
ref4 <- array(rnorm(60), dim = c(member = 2, sdate = 10, lat = 2))

##############################################
test_that("1. Input checks", {
  # exp and obs (1)
  expect_error(
   CRPSS(c()),
    "Parameter 'exp' must be a numeric array."
  )
  expect_error(
   CRPSS(exp1, c()),
    "Parameter 'obs' must be a numeric array."
  )

  # time_dim
  expect_error(
   CRPSS(exp1, obs1, time_dim = 1),
    "Parameter 'time_dim' must be a character string."
  )
  expect_error(
   CRPSS(exp1, obs1, time_dim = 'time'),
    "Parameter 'time_dim' is not found in 'exp' or 'obs' dimension."
  )
  expect_error(
   CRPSS(exp2, obs2, array(rnorm(20), dim = c(member = 2, time = 10))),
    "Parameter 'time_dim' is not found in 'ref' dimension."
  )
  # memb_dim
  expect_error(
   CRPSS(exp1, obs1, memb_dim = TRUE),
    "Parameter 'memb_dim' must be a character string."
  )
  expect_error(
   CRPSS(exp1, obs1, memb_dim = 'memb'),
    "Parameter 'memb_dim' is not found in 'exp' dimension."
  )
  expect_error(
   CRPSS(exp2, obs2, array(rnorm(20), dim = c(memb = 2, sdate = 10))),
    "Parameter 'memb_dim' is not found in 'ref' dimension."
  )
  # exp, ref, and obs (2)
  expect_error(
   CRPSS(exp1, array(1:9, dim = c(sdate = 9))),
    "Parameter 'exp' and 'obs' must have same length of all dimensions except 'memb_dim' and 'dat_dim'."
  )
  expect_error(
   CRPSS(exp2_2, obs2_2, array(1:9, dim = c(sdate = 9, member = 2, dataset = 3)), dat_dim = 'dataset'),
    "If parameter 'ref' has dataset dimension it must be equal to dataset dimension of 'exp'."
  )
  expect_error(
   CRPSS(exp1, obs1, ref2),
    "Parameter 'exp' and 'ref' must have same length of all dimensions except 'memb_dim' and 'dat_dim' if there is only one reference dataset."
  )
  expect_error(
   CRPSS(exp3, array(rnorm(60), dim = c(member = 2, sdate = 10, dataset = 3)), ref3, dat_dim = 'dataset'),
    "Not implemented for observations with members ('obs' can have 'memb_dim', but it should be of length = 1)."
    , fixed = TRUE
  )
  # Fair
  expect_error(
   CRPSS(exp1, obs1, Fair = 1),
    "Parameter 'Fair' must be either TRUE or FALSE."
  )
  # clim.cross.val
  expect_error(
   CRPSS(exp1, obs1, clim.cross.val = NA),
    "Parameter 'clim.cross.val' must be either TRUE or FALSE."
  )
  # ncores
  expect_error(
   CRPSS(exp2, obs2, ncores = 1.5),
    "Parameter 'ncores' must be either NULL or a positive integer."
  )

})

##############################################
test_that("2. Output checks: dat1", {

  expect_equal(
    names(CRPSS(exp1, obs1)),
    c("crpss", "sign")
  )
  expect_equal(
    names(CRPSS(exp1, obs1, ref1)),
    c("crpss", "sign")
  )
  expect_equal(
    dim(CRPSS(exp1, obs1)$crpss),
    c(lat = 2)
  )
  expect_equal(
    dim(CRPSS(exp1, obs1)$sign),
    c(lat = 2)
  )
  expect_equal(
    dim(CRPSS(exp1, obs1, ref1)$crpss),
    c(lat = 2)
  )
  expect_equal(
    dim(CRPSS(exp1, obs1, ref1)$sign),
    c(lat = 2)
  )
  # ref = NULL
  expect_equal(
    as.vector(CRPSS(exp1, obs1)$crpss),
    c(0.061796021, -0.003647287),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1)$sign),
    c(FALSE, FALSE)
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, Fair = T)$crpss),
    c(0.2612070, 0.1253865),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1)$crpss),
    c(0.061796021, -0.003647287),
    tolerance = 0.0001
  )
  # ref = ref
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref1)$crpss),
    c(0.3491793, 0.3379610),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref1)$sign),
    c(FALSE, FALSE)
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref1, Fair = T)$crpss),
    c( 0.3901440, 0.3788467),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref1)$crpss),
    c(0.3491793, 0.3379610),
    tolerance = 0.0001
  )
  # clim.cross.val
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref = NULL, clim.cross.val = F)$crpss),
    c(-0.1582765, -0.2390707),
    tolerance = 0.0001
  )

  # sig_method.type
  expect_equal(
    as.vector(CRPSS(exp1, obs1, sig_method.type = "two.sided", alpha = 0.15)$sign),
    c(FALSE, FALSE)
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, sig_method.type = "two.sided", alpha = 0.4)$sign),
    c(FALSE, TRUE)
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref1, sig_method.type = "two.sided", alpha = 0.15)$sign),
    c(TRUE, FALSE)
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref1, sig_method.type = "two.sided", alpha = 0.4)$sign),
    c(TRUE, FALSE)
  )
  expect_equal(
    as.vector(CRPSS(exp1, obs1, ref1, sig_method.type = "less", alpha = 0.15)$sign),
    c(FALSE, FALSE)
  )

})

##############################################
test_that("3. Output checks: dat2", {

  expect_equal(
    names(CRPSS(exp2, obs2)),
    c("crpss", "sign")
  )
  expect_equal(
    names(CRPSS(exp2, obs2, ref2)),
    c("crpss", "sign")
  )
  expect_equal(
    dim(CRPSS(exp2, obs2)$crpss),
    NULL
  )
  expect_equal(
    dim(CRPSS(exp2, obs2)$sign),
    NULL
  )
  expect_equal(
    dim(CRPSS(exp2, obs2, ref2)$crpss),
    NULL
  )
  expect_equal(
    dim(CRPSS(exp2, obs2, ref2)$sign),
    NULL
  )
  # ref = NULL
  expect_equal(
    as.vector(CRPSS(exp2, obs2)$crpss),
    -0.4749481,
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp2, obs2)$crpss),
    as.vector(CRPSS(exp2_2, obs2_2, dat_dim = 'dataset')$crpss),
    tolerance = 0.0001
  )

  expect_equal(
    as.vector(CRPSS(exp2, obs2)$sign),
    FALSE
  )
  expect_equal(
    as.vector(CRPSS(exp2, obs2, Fair = T)$crpss),
    c(-0.1745512),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp2, obs2, Fair = T)$crpss),
    as.vector(CRPSS(exp2_2, obs2_2, dat_dim = 'dataset', Fair = T)$crpss),
    tolerance = 0.0001
  )
  # ref = ref
  expect_equal(
    as.vector(CRPSS(exp2, obs2, ref2)$crpss),
    -0.02315361,
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp2, obs2, ref2)$crpss),
    as.vector(CRPSS(exp2_2, obs2_2, ref2_2, dat_dim = 'dataset')$crpss),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp2, obs2, ref2)$sign),
    FALSE
  )
  expect_equal(
    as.vector(CRPSS(exp2, obs2, ref2, Fair = T)$crpss),
    0.030436,
    tolerance = 0.0001
  )

})
##############################################
test_that("4. Output checks: dat3", {

  expect_equal(
    dim(CRPSS(exp3, obs3, dat_dim = 'dataset')$crpss),
    c('nexp' = 3, 'nobs' = 2)
  )
  expect_equal(
    mean(CRPSS(exp3, obs3, dat_dim = 'dataset')$crpss),
    c(-0.4086342),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp3, obs3, dat_dim = 'dataset')$crpss),
    c(-0.4749481, -0.3179303, -0.6871816, -0.3425333, -0.2936161, -0.3355958),
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp3, obs3, dat_dim = 'dataset')$sign),
    rep(FALSE, 6)
  )
  expect_equal(
    mean(CRPSS(exp3, obs3, dat_dim = 'dataset', Fair = T)$crpss),
    -0.2242162,
    tolerance = 0.0001
  )
  expect_equal(
    as.vector(CRPSS(exp3, obs3, dat_dim = 'dataset', Fair = T)$crpss),
    c(-0.17455119, -0.08645477, -0.60933021, -0.09844606, -0.11724947, -0.25926556),
    tolerance = 0.0001
  )
  # ref = ref3
  expect_equal(
    as.vector(CRPSS(exp3, obs3, ref = ref3, dat_dim = 'dataset')$crpss),
    c(-0.02315361, -0.05914715, -0.24638960, -0.09337738, 0.14668803, -0.01454008),
    tolerance = 0.0001
  )

  expect_equal(
   as.vector(CRPSS(exp3, obs3, dat_dim = 'dataset')$crpss[1]),
   as.vector(CRPSS(exp2, obs2)$crpss)
  )

  # sig_method.type
  expect_equal(
    as.vector(CRPSS(exp3, obs3, dat_dim = 'dataset', N.eff = FALSE, sig_method.type = "two.sided", alpha = 0.5)$sign),
    rep(F, 6)
  )
  expect_equal(
    as.vector(CRPSS(exp3, obs3, dat_dim = 'dataset', N.eff = NA, sig_method.type = "two.sided", alpha = 0.5)$sign),
    rep(T, 6)
  )
  expect_equal(
    as.vector(CRPSS(exp3, obs3, dat_dim = 'dataset', sig_method.type = "less", alpha = 0.5)$sign),
    rep(T, 6)
  )


})

##############################################
test_that("5. Output checks: dat4", {

  expect_equal(
    dim(CRPSS(exp4, obs4, ref4, dat_dim = 'dataset')$crpss),
    c('nexp' = 3, 'nobs' = 2, 'lat' = 2)
  )
  expect_equal(
    as.vector(CRPSS(exp4, obs4, dat_dim = 'dataset', Fair = T)$crpss)[1:6],
    c(-0.17455119, -0.08645477, -0.60933021, -0.09844606, -0.11724947, -0.25926556),
    tolerance = 0.0001
  )
  # ref = ref3
  expect_equal(
    as.vector(CRPSS(exp4, obs4, ref = ref4, dat_dim = 'dataset')$crpss)[1:6],
    c(-0.02315361, 0.08576776, -0.17037744, -0.09337738, -0.05353853, -0.08772739),
    tolerance = 0.0001
  )


})
