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

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

  set.seed(2)
  obs1 <- array(rnorm(30), dim = c(member = 1, sdate = 5,
                                   ftime = 1, lat = 2, lon = 3))
  lat1 <- c(30, 35)
  lon1 <- c(0, 5, 10)

  set.seed(2)
  obs1_2 <- array(rnorm(30), dim = c(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
  lat2 <- c(30, 35)
  lon2 <- c(0, 5, 10)

  # dat3
  set.seed(1)
  exp3 <- array(rnorm(72), dim = c(dat = 2, member = 3, sdate = 3, lat = 2, lon = 2))
  set.seed(2)
  obs3 <- array(rnorm(12), dim = c(dat = 1, sdate = 3, lat = 2, lon = 2))
  lat3 <- c(0, 10)

##############################################
test_that("1. Input checks", {
  # exp and obs (1)
  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 ",
         "lat_dim and lon_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."
  )
  # dat_dim
  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."
  )
  # lat_dim
  expect_error(
  ACC(exp1, obs1, lat_dim = 1),
  "Parameter 'lat_dim' must be a character string."
  )
  expect_error(
  ACC(exp1, obs1, lat_dim = 'latitude'),
  "Parameter 'lat_dim' is not found in 'exp' or 'obs' dimension."
  )
  # lon_dim
  expect_error(
  ACC(exp1, obs1, lon_dim = 2),
  "Parameter 'lon_dim' must be a character string."
  )
  expect_error(
  ACC(exp1, obs1, lon_dim = 'lonn'),
  "Parameter 'lon_dim' is not found in 'exp' or 'obs' dimension."
  )
  # avg_dim
  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."
  )
  # memb_dim
  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' nor 'obs' dimension. Set it as NULL if there is no member dimension."
  )
  # lat
  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\'.")
  )
  # lon
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 3)),
  paste0("Parameter \'lon\' must be a numeric vector with the same ",
         "length as the longitude dimension of \'exp\' and \'obs\'.")
  )
  # lonlatbox
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3), lonlatbox = c(-90, 90)),
  "Parameter 'lonlatbox' must be a numeric vector of 4."
  )
  # conf
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3), conf = 1),
  "Parameter 'conf' must be one logical value."
  )
  # conftype
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3), conftype = 'a'),
  "Parameter \'conftype\' must be either \'parametric\' or \'bootstrap\'."
  )
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3), memb_dim = NULL, conftype = 'bootstrap'),
  "Parameter 'memb_dim' cannot be NULL when parameter 'conftype' is 'bootstrap'."
  )
  # alpha
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3), alpha = -1),
  "Parameter 'alpha' must be a numeric number between 0 and 1."
  )
  # pval
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3), pval = 'TRUE'),
  "Parameter 'pval' must be one logical value."
  )
  # ncores
  expect_error(
  ACC(exp1, obs1, lat = c(1, 2), lon = c(1, 2, 3), ncores = 1.5),
  "Parameter 'ncores' must be a positive integer."
  )
  # exp and obs (2)
  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)),
      lat = c(1, 2), lon = c(1),
      avg_dim = NULL),
  "Parameter 'exp' and 'obs' must have same length of all the dimensions except 'dat_dim' and 'memb_dim'."
  )

})

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

  expect_equal(
    dim(ACC(exp1, obs1, lat = lat1, lon = lon1)$acc),
    c(sdate = 5, ftime = 1)
  )
  expect_equal(
    names(ACC(exp1, obs1, lat = lat1)),
    c("acc", "macc", "conf.lower", "conf.upper", "p.val")
  )
  expect_equal(
    as.vector(ACC(exp1, obs1, lat = lat1)$acc),
    c(-0.006384684, -0.664580451, -0.637292180, 0.320974249, -0.453246995),
    tolerance = 0.00001
  )
  expect_equal(
    as.vector(ACC(exp1, obs1, lat = lat1)$p.val),   
    c(0.7292993, 0.7292993, 0.7292993, 0.7292993, 0.7292993),
    tolerance = 0.00001    
  )
  expect_equal(
    as.vector(ACC(exp1, obs1, lat = lat1)$conf.lower),
    c(-0.8137296, -0.9589397, -0.9549511, -0.6633950, -0.9246771),
    tolerance = 0.00001
  )
  expect_equal(
    as.vector(ACC(exp1, obs1, lat = lat1)$conf.upper),
    c(0.8093704, 0.3190711, 0.3609563, 0.8984881, 0.5668074),
    tolerance = 0.00001
  )
  expect_equal(
    names(ACC(exp1, obs1, lat = lat1, avg_dim = NULL)),
    c("acc", "conf.lower", "conf.upper", "p.val")
  )
  expect_equal(
    dim(ACC(exp1, obs1, lat = lat1, dat_dim = 'member', memb_dim = NULL)$acc),
    c(nexp = 2, nobs = 1, sdate = 5, ftime = 1)
  )
  expect_equal(
    names(ACC(exp1, obs1, lat = lat1, conf = FALSE)),
    c("acc", "macc", "p.val")
  )
  expect_equal(
    names(ACC(exp1, obs1, lat = lat1, pval = FALSE)),
    c("acc", "macc", "conf.lower", "conf.upper")
  )
  expect_equal(
    names(ACC(exp1, obs1, lat = lat1, conf = FALSE, pval = FALSE)),
    c("acc", "macc")
  )
  expect_equal(
    as.vector(ACC(exp1, obs1, lat = lat1, conf = FALSE, avg_dim = NULL, alpha = 0.1)$p.val),
    c(0.6083998, 0.6083998, 0.6083998, 0.6083998, 0.6083998),
    tolerance = 0.00001
  )
  expect_equal(
    as.vector(ACC(exp1, obs1, lat = c(10, 20), lon = c(20, 30, 40), lonlatbox = c(20, 30, 10, 20))$acc),
    c(0.3555372, -0.5205672, -0.3403301, 0.2690648, -0.5146910),
    tolerance = 0.00001
  )

  # bootstrap
  expect_equal(
  names(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap')),
  c('acc', 'acc_conf.lower', 'acc_conf.upper', 'macc', 'macc_conf.lower', 'macc_conf.upper')
  )
  expect_equal(
  dim(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap')$acc),
  c(sdate = 5, ftime = 1)
  )
  expect_equal(
  dim(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap')$acc_conf.lower),
  c(sdate = 5, ftime = 1)
  )
  expect_equal(
  dim(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap')$macc_conf.lower),
  c(ftime = 1)
  )
  expect_equal(
  dim(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap')$macc),
  c(ftime = 1)
  )
  # boostrap, avg_time is NULL
  expect_equal(
  names(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap', avg_dim = NULL)),
  c('acc', 'acc_conf.lower', 'acc_conf.upper', 'macc', 'macc_conf.lower', 'macc_conf.upper')
  )
  expect_equal(
  dim(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap', avg_dim = NULL)$acc),
  c(sdate = 5, ftime = 1)
  )
  expect_equal(
  dim(ACC(exp1, obs1, lat = lat1, lon = lon1, conftype = 'bootstrap', avg_dim = NULL)$acc_conf.lower),
  c(sdate = 5, ftime = 1)
  )

  # obs1_2, no memb_dim 
  expect_equal(
  ACC(exp1, obs1, lat = lat1),
  ACC(exp1, obs1_2, lat = lat1)
  )
})


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

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

expect_equal(
  dim(ACC(exp2, obs2, lat = lat2, lon = lon2, memb_dim = NULL, dat_dim = 'dataset')$acc),
  c(nexp = 2, nobs = 1, sdate = 5, ftime = 1)
)
expect_equal(
  as.vector(ACC(exp2, obs2, lat = lat2, memb_dim = NULL, dat_dim = 'dataset')$acc)[3:7],
  c(-0.3601880, -0.5624773, -0.4603762, -0.6997169, -0.1336961),
  tolerance = 0.00001
)
expect_equal(
  mean(ACC(exp2, obs2, lat = lat2, memb_dim = NULL, dat_dim = 'dataset')$acc),
  -0.1484762,
  tolerance = 0.00001
)

})


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

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

expect_equal(
names(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat")),
c('acc', 'macc', 'conf.lower', 'conf.upper', 'p.val')
)
expect_equal(
names(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat", avg_dim = NULL)),
c('acc', 'conf.lower', 'conf.upper', 'p.val')
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat")$acc),
c(nexp = 2, nobs = 1, sdate = 3)
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat", avg_dim = NULL)$acc),
c(nexp = 2, nobs = 1, sdate = 3)
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat")$p.val),
c(nexp = 2, nobs = 1, sdate = 3)
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat")$conf.upper),
c(nexp = 2, nobs = 1, sdate = 3)
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat")$macc),
c(nexp = 2, nobs = 1)
)

expect_equal(
ACC(exp3, array(obs3, c(member = 1, dim(obs3))), lat = lat3, memb_dim = "member", dat_dim = "dat"),
ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat")
)

# bootstrap
expect_equal(
names(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat", conftype = 'bootstrap')),
c('acc', 'acc_conf.lower', 'acc_conf.upper', 'macc', 'macc_conf.lower', 'macc_conf.upper')
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat", conftype = 'bootstrap')$acc),
c(nexp = 2, nobs = 1, sdate = 3)
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat", conftype = 'bootstrap')$acc_conf.lower),
c(nexp = 2, nobs = 1, sdate = 3)
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat", conftype = 'bootstrap')$macc),
c(nexp = 2, nobs = 1)
)
expect_equal(
dim(ACC(exp3, obs3, lat = lat3, memb_dim = "member", dat_dim = "dat", conftype = 'bootstrap')$macc_conf.upper),
c(nexp = 2, nobs = 1)
)

})
