context("s2dv::ACC tests")

##############################################
##NOTE: bootstrap is not tested because sample() is used inside.

  # dat1
  set.seed(1)
  exp1 <- array(rnorm(60), dim = c(dataset = 1, member = 2, sdate = 5,
                                   ftime = 1, lat = 2, lon = 3))

  set.seed(2)
  obs1 <- array(rnorm(30), dim = c(dataset = 1, member = 1, sdate = 5,
                                   ftime = 1, lat = 2, lon = 3))
  # dat2
  set.seed(1)
  exp2 <- array(rnorm(60), dim = c(dataset = 2, sdate = 5,
                                   ftime = 1, lat = 2, lon = 3))
  set.seed(2)
  obs2 <- array(rnorm(30), dim = c(dataset = 1, sdate = 5,
                                   ftime = 1, lat = 2, lon = 3))
  set.seed(2)
  na <- floor(runif(2, min = 1, max = 30))
  obs2[na] <- NA

##############################################
test_that("1. Input checks", {

  expect_error(
  ACC(c(), c()),
  "Parameter 'exp' and 'obs' cannot be NULL."
  )
  expect_error(
  ACC(c('b'), c('a')),
  "Parameter 'exp' and 'obs' must be a numeric array."
  )
  expect_error(
  ACC(c(1:10), c(2:4)),
  paste0("Parameter 'exp' and 'obs' must have at least dimensions ",
         "dat_dim and space_dim.")
  )
  expect_error(
  ACC(array(1:10, dim = c(2, 5)), array(1:4, dim = c(2, 2))),
  "Parameter 'exp' and 'obs' must have dimension names."
  )
  expect_error(
  ACC(array(1:10, dim = c(a = 2, c = 5)), array(1:4, dim = c(a = 2, b = 2))),
  "Parameter 'exp' and 'obs' must have same dimension name"
  )
  expect_error(
  ACC(exp1, obs1, dat_dim = 1),
  "Parameter 'dat_dim' must be a character string."
  )
  expect_error(
  ACC(exp1, obs1, dat_dim = 'a'),
  "Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension."
  )
  expect_error(
  ACC(exp1, obs1, space_dim = c('lon')),
  "Parameter 'space_dim' must be a character vector of 2."
  )
  expect_error(
  ACC(exp1, obs1, space_dim = c('lon', 'lev')),
  "Parameter 'space_dim' is not found in 'exp' or 'obs' dimension."
  )
  expect_error(
  ACC(exp1, obs1, avg_dim = 1),
  "Parameter 'avg_dim' must be a character string."
  )
  expect_error(
  ACC(exp1, obs1, avg_dim = c('lev')),
  "Parameter 'avg_dim' is not found in 'exp' or 'obs' dimension."
  )
  expect_error(
  ACC(exp1, obs1, memb_dim = TRUE),
  "Parameter 'memb_dim' must be a character string."
  )
  expect_error(
  ACC(exp1, obs1, memb_dim = 'memb'),
  "Parameter 'memb_dim' is not found in 'exp' or 'obs' dimension."
  )
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2, 3)),
  paste0("Parameter \'lat\' must be a numeric vector with the same ",
         "length as the latitude dimension of \'exp\' and \'obs\'.")
  )
  expect_error(
  ACC(exp1, obs1, lon = c(1, 3)),
  paste0("Parameter \'lon\' must be a numeric vector with the same ",
         "length as the longitude dimension of \'exp\' and \'obs\'.")
  )
  expect_error(
  ACC(exp1, obs1, lonlatbox = c(-90, 90)),
  "Parameter 'lonlatbox' must be a numeric vector of 4."
  )
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3)),
  paste0("Parameters 'lon', 'lat', and 'lonlatbox' must be used or be ",
         "NULL at the same time.")
  )
  expect_error(
  ACC(exp1, obs1, conf = 1),
  "Parameter 'conf' must be one logical value."
  )
  expect_error(
  ACC(exp1, obs1, conftype = 'a'),
  "Parameter \'conftype\' must be either \'parametric\' or \'bootstrap\'."
  )
  expect_error(
  ACC(exp1, obs1, memb_dim = NULL, conftype = 'bootstrap'),
  "Parameter 'memb_dim' cannot be NULL when parameter 'conftype' is 'bootstrap'."
  )
  expect_error(
  ACC(exp1, obs1, conf.lev = -1),
  "Parameter 'conf.lev' must be a numeric number between 0 and 1."
  )
  expect_error(
  ACC(exp1, obs1, pval = 'TRUE'),
  "Parameter 'pval' must be one logical value."
  )
  expect_error(
  ACC(exp1, obs1, ncores = 1.5),
  "Parameter 'ncores' must be a positive integer."
  )
  expect_error(
  ACC(exp = array(1:10, dim = c(dataset = 5, member = 1, lat = 2, lon = 1)),
      obs = array(1:4, dim = c(dataset = 2, member = 2, lat = 1, lon = 1)),
      avg_dim = NULL),
  "Parameter 'exp' and 'obs' must have same length of all the dimensions expect 'dat_dim' and 'memb_dim'."
  )

})

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

  expect_equal(
    dim(ACC(exp1, obs1)$acc),
    c(nexp = 1, nobs = 1, sdate = 5, ftime = 1)
  )
  expect_equal(
    names(ACC(exp1, obs1)),
    c("acc", "conf.lower", "conf.upper", "p.val", "macc")
  )
  expect_equal(
    mean(ACC(exp1, obs1)$acc),
    -0.2001352,
    tolerance = 0.00001
  )
  expect_equal(
    as.vector(ACC(exp1, obs1)$p.val),   
    c(0.7292993, 0.7292993, 0.7292993, 0.7292993, 0.7292993),
    tolerance = 0.00001    
  )
  expect_equal(
    as.vector(ACC(exp1, obs1)$conf.lower),
    c(-0.8595534, -0.9644555, -0.9408508, -0.6887500, -0.7619374),
    tolerance = 0.00001
  )
  expect_equal(
    as.vector(ACC(exp1, obs1)$conf.upper),
    c(0.7493799, 0.2515608, 0.4759707, 0.8890967, 0.8517117),
    tolerance = 0.00001
  )
  expect_equal(
    names(ACC(exp1, obs1, avg_dim = NULL)),
    c("acc", "conf.lower", "conf.upper", "p.val")
  )
  expect_equal(
    dim(ACC(exp1, obs1, dat_dim = 'member', memb_dim = NULL)$acc),
    c(nexp = 2, nobs = 1, sdate = 5, dataset = 1, ftime = 1)
  )
  expect_equal(
    names(ACC(exp1, obs1, conf = FALSE)),
    c("acc", "p.val", "macc")
  )
  expect_equal(
    names(ACC(exp1, obs1, pval = FALSE)),
    c("acc", "conf.lower", "conf.upper", "macc")
  )
  expect_equal(
    names(ACC(exp1, obs1, conf = FALSE, pval = FALSE)),
    c("acc", "macc")
  )
  expect_equal(
    as.vector(ACC(exp1, obs1, conf = FALSE, avg_dim = NULL, conf.lev = 0.9)$p.val),
    c(0.6083998, 0.6083998, 0.6083998, 0.6083998, 0.6083998),
    tolerance = 0.00001
  )
  expect_equal(
    mean(ACC(exp1, obs1, lat = c(10, 20), lon = c(20, 30, 40), lonlatbox = c(20, 30, 10, 20))$acc),
    -0.1681097,
    tolerance = 0.00001
  )
})





