context("s2dv::Composite tests")

##############################################
  # dat1
  x1 <- array(0, dim = c(20, 10, 30))
  t1 <- array(0, dim = c(20, 10, 30))
  dat1 <- array(0, dim = c(20, 10, 30))
  
  for (i in 1:20) {
   x1[i, , ] <- i
  }
  for (i in 1:30) {
   t1[, , i] <- i
  }
  for (i in 1:20) {
   for (j in 1:30) {
     dat1[i,, j ] <- 3 * sin(2 * pi * x1[i, , j] / 5. - 2 * pi * t1[i, , j] / 6.)
   }
  }
  names(dim(dat1)) <- c('lon', 'lat', 'time')
  occ1 <- rep(0, 30)
  occ1[c(2, 5, 8, 11, 14, 17, 20, 23)] <- 1

  # dat2
  dat2 <- array(0, dim = c(dat = 2, longitude = 20, latitude = 10, sdate = 30))
  dat2[1, , , ] <- dat1
  set.seed(1)
  dat2[2, , , ] <- dat1 + rnorm(n = 6000, mean = mean(dat1), sd = sd(dat1)/10)

  occ2 <- rep(0, 30)
  occ2[c(2, 5, 8, 11, 14, 17, 20, 23)] <- 1
  occ2[c(1, 4, 10, 13, 19, 24, 29)] <- 2

  # dat3
  dat3 <- array(rep(c(1, 3, 2, 1, 2, 2), 8), dim = c(x = 2, y = 4, time = 6))
  occ3 <- c(1, 1, 4, 4, 3, 3)

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

test_that("1. Input checks", {
  # data
  expect_error(
  Composite(c()),
  "Parameter 'data' cannot be NULL."
  )
  expect_error(
    Composite(c(NA, NA)),
    "Parameter 'data' must be a numeric array."
  )
  expect_error(
    Composite(c(1:10)),
    "Parameter 'data' must have at least three dimensions."
  )
  expect_error(
    Composite(array(1:10, dim = c(2, 5, 2))),
    "Parameter 'data' must have dimension names."
  )
  # occ
  expect_error(
    Composite(dat1, c()),
    "Parameter 'occ' cannot be NULL."
  )
  expect_error(
    Composite(dat1, c(NA, NA)),
    "Parameter 'occ' must be a numeric vector."
  )
  expect_error(
    Composite(dat1, array(1:10, dim = c(2, 5, 2))),
    "Parameter 'occ' must be a numeric vector."
  )
  # time_dim
  expect_error(
    Composite(dat1, occ1, time_dim = 2),
    "Parameter 'time_dim' must be a character string."
  )
  expect_error(
    Composite(dat1, occ1, time_dim = 'sdate'),
    "Parameter 'time_dim' is not found in 'data' dimension."
  )
  expect_error(
    Composite(dat1, c(occ1, 1)),
    paste0("The length of time_dim dimension in parameter 'data' is not ",
           "equal to length of parameter 'occ'.")
  )
  # space_dim
  expect_error(
    Composite(dat1, occ1, space_dim = 'lon'),
    "Parameter 'space_dim' must be a character vector with two elements."
  )
  expect_error(
    Composite(dat1, occ1, space_dim = c('lon', 'level')),
    "Parameter 'space_dim' is not found in 'data' dimension."
  )
  # lag
  expect_error(
    Composite(dat1, occ1, lag = -1),
    "Parameter 'lag' must be a non-negative integer."
  )
  # eno
  expect_error(
    Composite(dat1, occ1, eno = 1),
    "Parameter 'eno' must be one logical value."
  )
  # K
  expect_error(
    Composite(dat1, occ1, K = 1.5),
    "Parameter 'K' must be a positive integer."
  )
  # fileout
  expect_error(
    Composite(dat1, occ1, fileout = TRUE),
    "Parameter 'fileout' must be a character string."
  )
  #ncores
  expect_error(
    Composite(dat1, occ1, ncores = 1.2),
    "Parameter 'ncores' must be a positive integer."
  )

  expect_warning(
    Composite(data = array(1:40, dim = c(lon = 2, lat = 5, time = 4)), 
              occ =  c(1, 2, 2, 2)),
    "Composite K = 1 has length 1. The p-value is NA."
  )

})


test_that("2. dat1", {

  expect_equal(
    dim(Composite(dat1, occ1)$composite),
    c(lon = 20, lat = 10, K = 1)
  )
  expect_equal(
    dim(Composite(dat1, occ1)$p.val),
    c(lon = 20, lat = 10, K = 1)
  )
  expect_equal(
    mean(Composite(dat1, occ1)$composite)*10^17,
    -3.816392,
    tolerance = 0.00001
  )
  expect_equal(
    Composite(dat1, occ1)$composite[5, 5, 1]*10^16,
    2.220446,
    tolerance = 0.00001
  )
  expect_equal(
    mean(Composite(dat1, occ1)$p.val),
    1,
    tolerance = 0.00001
  )
  expect_equal(
    mean(Composite(dat1, occ2, eno = TRUE)$composite[, , 1])*10^17,
    -3.816392,
    tolerance = 0.00001
  )

})

test_that("3. dat2", {

  expect_equal(
    dim(Composite(dat2, occ2, time_dim = 'sdate')$composite),
    c(longitude = 20, latitude = 10, K = 2, dat = 2)
  )
  expect_equal(
    dim(Composite(dat2, occ2, time_dim = 'sdate')$p.val),
    c(longitude = 20, latitude = 10, K = 2, dat = 2)
  )
  expect_equal(
    dim(Composite(dat2, occ2, time_dim = 'sdate', K = 1)$composite),
    c(longitude = 20, latitude = 10, K = 1, dat = 2)
  )
  expect_equal(
    mean(Composite(dat2, occ2, eno = TRUE, time_dim = 'sdate')$composite[, , 1, 1])*10^17,
    -3.816392,
    tolerance = 0.00001
  )
  expect_equal(
    mean(Composite(dat2, occ2, time_dim = 'sdate')$composite[, , 2, 1])*10^17,
    -3.908599,
    tolerance = 0.001
  )
  expect_equal(
    mean(Composite(dat2, occ2, time_dim = 'sdate')$composite[, , 1, 2]),
    0.00309623,
    tolerance = 0.00001
  )
  expect_equal(
    mean(Composite(dat2, occ2, time_dim = 'sdate')$p.val[, , 2, 2]),
    0.5632136,
    tolerance = 0.00001
  )
  expect_equal(
    mean(Composite(dat2, occ2, time_dim = 'sdate', eno = TRUE)$p.val[, , 2, 2]),
    0.5639538,
    tolerance = 0.00001
  )
})

test_that("4. dat3", {

  expect_equal(
  dim(Composite(dat3, occ3, space_dim = c('x', 'y'))$composite),
  c(x = 2, y = 4, K = 4)
  )
  expect_equal(
    all(is.na(Composite(dat3, occ3, space_dim = c('x', 'y'))$composite[, , 2])),
    TRUE
  )
  expect_equal(
    sd(Composite(dat3, occ3, space_dim = c('x', 'y'))$composite[, , 4]),
    0.4432026,
    tolerance = 0.0001
  )
  expect_equal(
    mean(Composite(dat3, occ3, space_dim = c('x', 'y'))$p.val[, , 1]),
    0.6954875,
    tolerance = 0.0001
  )

})

