context("s2dv::ROCSS tests")

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

# 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))

# dat1_2
exp1_2 <- GetProbs(exp1, memb_dim = 'member')
obs1_2 <- GetProbs(obs1, memb_dim = NULL)
ref1_2 <- GetProbs(ref1, memb_dim = 'member')

# dat2
set.seed(1)
exp2 <- array(rnorm(30), dim = c(member = 3, 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))


# 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))
set.seed(3)
ref3_2 <- array(rnorm(20), dim = c(member = 2, sdate = 10))

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

  # time_dim
  expect_error(
    ROCSS(exp1, obs1, time_dim = 1),
    "Parameter 'time_dim' must be a character string."
  )
  expect_error(
    ROCSS(exp1, obs1, time_dim = 'time'),
    "Parameter 'time_dim' is not found in 'exp' or 'obs' dimension."
  )
  expect_error(
    ROCSS(exp2, obs2, array(rnorm(20), dim = c(member = 2, time = 10))),
    "Parameter 'time_dim' is not found in 'ref' dimension."
  )
  # memb_dim
  expect_error(
    ROCSS(exp1, obs1, memb_dim = TRUE),
    "Parameter 'memb_dim' must be a character string."
  )
  expect_error(
    ROCSS(exp1, obs1, memb_dim = 'memb'),
    "Parameter 'memb_dim' is not found in 'exp' dimension."
  )
  expect_error(
    ROCSS(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(
    ROCSS(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(
    ROCSS(exp3, obs3, array(rnorm(60), dim = c(member = 2, sdate = 10, dataset = 4)), dat_dim = 'dataset'),
    "If parameter 'ref' has dataset dimension, it must be equal to dataset dimension of 'exp'."
  )
  expect_error(
    ROCSS(exp1, obs1, ref2),
    "Parameter 'exp' and 'ref' must have the same length of all dimensions except 'memb_dim' and 'dat_dim' if there is only one reference dataset."
  )
  # prob_thresholds
  expect_error(
    ROCSS(exp1, obs1, ref1, prob_thresholds = 1),
    "Parameter 'prob_thresholds' must be a numeric vector between 0 and 1."
  )
  # indices_for_clim
  expect_error(
    ROCSS(exp1, obs1, ref1, indices_for_clim = array(1:6, dim = c(2, 3))),
    "Parameter 'indices_for_clim' must be NULL or a numeric vector."
  )
  expect_error(
    ROCSS(exp1, obs1, indices_for_clim = 3:11),
    "Parameter 'indices_for_clim' should be the indices of 'time_dim'."
  )
  # cross.val
  expect_error(
  ROCSS(exp1, obs1, cross.val = 1),
  "Parameter 'cross.val' must be either TRUE or FALSE."
  )

  # ncores
  expect_error(
    ROCSS(exp2, obs2, ncores = 1.5),
    "Parameter 'ncores' must be either NULL or a positive integer."
  )

})

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

expect_equal(
  dim(ROCSS(exp1, obs1)),
  c(cat = 3, lat = 2)
)
expect_equal(
  dim(ROCSS(exp1, obs1, ref1)),
  c(cat = 3, lat = 2)
)
expect_equal(
c(ROCSS(exp1, obs1)[1, ]),
c(0.3333333, 0.0000000),
tolerance = 0.0001
)
expect_equal(
c(ROCSS(exp1, obs1)[2, ]),
c(0.0000000, 0.6666667),
tolerance = 0.0001
)
expect_equal(
c(ROCSS(exp1, obs1)[3, ]),
c(0.5238095, 0.3809524),
tolerance = 0.0001
)
# with ref
expect_equal(
c(ROCSS(exp1, obs1, ref1)[1, ]),
c(0.53333333, 0.08695652),
tolerance = 0.0001
)
expect_equal(
c(ROCSS(exp1, obs1, ref1)[2, ]),
c(0.4545455, 0.6190476),
tolerance = 0.0001
)
expect_equal(
c(ROCSS(exp1, obs1, ref1)[3, ]),
c(0.5238095, 0.5357143),
tolerance = 0.0001
)

# dat1_2
expect_equal(
  ROCSS(exp1, obs1),
  ROCSS(exp1_2, obs1_2, memb_dim = NULL, cat_dim = 'bin')
)
expect_equal(
  ROCSS(exp1, obs1, ref1),
  ROCSS(exp1_2, obs1_2, ref1_2, memb_dim = NULL, cat_dim = 'bin')
)

})

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

expect_equal(
  dim(ROCSS(exp2, obs2, prob_thresholds = c(0.25, 0.5, 0.75))),
  c(cat = 4)
)
expect_equal(
  dim(ROCSS(exp2, obs2, ref2, prob_thresholds = c(0.25, 0.5, 0.75))),
  c(cat = 4)
)
# without ref
expect_equal(
c(ROCSS(exp2, obs2)),
c(0.3333333, 0, 0.5238095),
tolerance = 0.0001
)
expect_equal(
c(ROCSS(exp2, obs2, prob_thresholds = c(0.25, 0.5, 0.75))),
c(0.1875000, -0.0952381, 0.0000000, -0.7500000),
tolerance = 0.0001
)
expect_equal(
c(ROCSS(exp2, obs2, indices_for_clim = 2:6)),
c(0.56, 0.00, 0.25),
tolerance = 0.0001
)
expect_equal(
c(ROCSS(exp2, obs2, ref2, indices_for_clim = 2:6)),
c(0.6333333, 0.0000000, 0.2500000),
tolerance = 0.0001
)


})

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

expect_equal(
  dim(ROCSS(exp3, obs3, dat_dim = 'dataset')),
  c(nexp = 3, nobs = 2, cat = 3)
)
expect_equal(
  dim(ROCSS(exp3, obs3, ref3, dat_dim = 'dataset')),
  c(nexp = 3, nobs = 2, cat = 3)
)
expect_equal(
  dim(ROCSS(exp3, obs3, ref3_2, dat_dim = 'dataset')),
  c(nexp = 3, nobs = 2, cat = 3)
)

expect_equal(
  c(ROCSS(exp3, obs3, ref3, dat_dim = 'dataset')[1, , ]),
  c(0.3, -0.25, 0.3636364, -0.8095238, -0.4285714,0),
  tolerance = 0.0001
)
expect_equal(
  c(ROCSS(exp3, obs3, ref3, dat_dim = 'dataset')[2, , ]),
  c(0.5652174, 0, 0, -0.4285714, -0.4, 0),
  tolerance = 0.0001
)
expect_equal(
  c(ROCSS(exp3, obs3, ref3_2, dat_dim = 'dataset')[1, , ]),
  c(0.3, -0.25, 0.3636364, -0.8095238, -0.4285714, 0),
  tolerance = 0.0001
)
expect_equal(
  c(ROCSS(exp3, obs3, ref3_2, dat_dim = 'dataset')[2, , ]),
  c(0.66666667, 0.04166667, 0.40909091, -0.42857143, -0.33333333, -0.33333333),
  tolerance = 0.0001
)

})
