context("s2dv::ProjectField tests")

##############################################
  # dat1
  set.seed(1)
  dat1 <- array(rnorm(120), dim = c(sdate = 10, lat = 6, lon = 2))
  lat1 <- seq(10, 30, length.out = 6)
  lon1 <- c(10, 12)
  eof1 <- EOF(dat1, lat1, lon1)

  # dat2
  set.seed(1)
  dat2 <- array(rnorm(48), dim = c(dat = 1, memb = 1, sdate = 6, ftime = 1, lat = 4, lon = 2))
  lat2 <- seq(10, 30, length.out = 4)
  lon2 <- c(-5, 5)
  eof2 <- EOF(dat2, lat2, lon2)
 
  # dat3
  dat3 <- dat2
  dat3[1, 1, 1, 1, , ] <- NA
  names(dim(dat3)) <- names(dim(dat2))
  lat3 <- seq(10, 30, length.out = 4)
  lon3 <- c(-5, 5)
  eof3 <- EOF(dat3, lat3, lon3)

  # dat4
  set.seed(1)
  dat4 <- array(rnorm(288), dim = c(dat = 1, memb = 2, sdate = 6, ftime = 3, lat = 4, lon = 2))
  lat4 <- seq(-10, -30, length.out = 4)
  lon4 <- c(350, 355)
  eof4 <- EOF(dat4, lat4, lon4)

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

  # ano
  expect_error(
  ProjectField(c()),
  "Parameter 'ano' cannot be NULL."
  )
  expect_error(
    ProjectField(c(NA, NA)),
    "Parameter 'ano' must be a numeric array."
  )
  expect_error(
    ProjectField(list(a = array(rnorm(50), dim = c(dat = 5, sdate = 10)), b = c(1:4))),
    "Parameter 'ano' must be a numeric array."
  )
  expect_error(
    ProjectField(array(1:10, dim = c(2, 5))),
    "Parameter 'ano' must have dimension names."
  )
  # eof
  expect_error(
  ProjectField(dat1, c()),
  "Parameter 'eof' cannot be NULL."
  )
  expect_error(
  ProjectField(dat1, c(1, 2, 3)),
  "Parameter 'eof' must be a list generated by EOF()."
  )
  expect_error(
  ProjectField(dat1, list(a = 1)),
  "Parameter 'eof' must contain 'EOFs' and 'wght' generated by EOF()."
  )
  eof_fake <- list(EOFs = 'a', wght = 1:10)
  expect_error(
  ProjectField(dat1, eof_fake),
  "The component 'EOFs' of parameter 'eof' must be a numeric array."
  )
  eof_fake <- list(EOFs = array(rnorm(10), dim = c(mode = 1, lat = 2, lon = 5)), 
                   wght = c(1:10))
  expect_error(
  ProjectField(dat1, eof_fake),
  "The component 'wght' of parameter 'eof' must be a numeric array."
  )
  # time_dim
  expect_error(
    ProjectField(dat1, eof1, time_dim = 2),
    "Parameter 'time_dim' must be a character string."
  )
  expect_error(
    ProjectField(dat1, eof1, time_dim = c('a','sdate')),
    "Parameter 'time_dim' must be a character string."
  )
  # space_dim
  expect_error(
    ProjectField(dat1, eof1, space_dim = 'lat'),
    "Parameter 'space_dim' must be a character vector of 2."
  )
  expect_error(
    ProjectField(dat1, eof1, space_dim = c('latitude', 'longitude')),
    "Parameter 'space_dim' is not found in 'ano' dimension."
  )
  # eof (2)
  eof_fake <- list(EOFs = array(rnorm(10), dim = c(lat = 2, lon = 5)), 
                   wght = array(rnorm(10), dim = c(lat = 2, lon = 5)))
  expect_error(
  ProjectField(dat1, eof_fake),
  paste0("The component 'EOFs' of parameter 'eof' must be an array ",
         "with dimensions named as parameter 'space_dim' and 'mode'.")
  )
  eof_fake <- list(EOFs = array(rnorm(10), dim = c(mode = 1, lat = 6, lon = 3)),          
                   wght = array(rnorm(10), dim = c(lat = 6, lon = 2))) 
  expect_error(
  ProjectField(dat1, eof_fake),
  paste0("The component 'EOFs' of parameter 'eof' must have the ",
         "same dimensions as 'ano' except that 'ano' does not have ",
         "'mode' and 'EOFs' does not have time_dim.")
  )
  eof_fake <- list(EOFs = array(rnorm(10), dim = c(mode = 1, lat = 6, lon = 2)),
                   wght = array(rnorm(10), dim = c(level = 6, lon = 2)))
  expect_error(
  ProjectField(dat1, eof_fake),
  paste0("The component 'wght' of parameter 'eof' must be an array ",
         "with dimensions named as parameter 'space_dim'.")
  )
  # mode
  expect_error(
    ProjectField(dat1, eof1, mode = -1),
    "Parameter 'mode' must be a positive integer."
  )
  expect_error(
    ProjectField(dat1, eof1, mode = 15),
    paste0("Parameter 'mode' is greater than the number of available ",
                "modes in EOF.")
  )
  # ncores
  expect_error(
    ProjectField(dat1, eof1, ncore = 3.5),
    "Parameter 'ncores' must be a positive integer."
  )

})
##############################################
test_that("2. dat1", {

  expect_equal(
  dim(ProjectField(dat1, eof = eof1)),
  c(sdate = 10)
  )
  expect_equal(
  as.vector(ProjectField(dat1, eof1))[1:5],
  c(3.2061306, -0.1692669, 0.5420990, -2.5324441, -0.6143680),
  tolerance = 0.0001
  )
  expect_equal(
  as.vector(ProjectField(dat1, eof1, mode = 10))[1:5],
  c(-0.24848299, -0.19311118, -0.16951195, -0.10000207, 0.04554693),
  tolerance = 0.0001
  )

})
##############################################
test_that("3. dat2", {
  expect_equal(
  dim(ProjectField(dat2, eof2)),
  c(sdate = 6, dat = 1, memb = 1, ftime = 1)
  )
  expect_equal(
  ProjectField(dat2, eof2)[1:6],
  c(0.00118771, -1.20872474, -0.00821559, -2.06064916, -0.19245169, 2.26026937),
  tolerance = 0.0001
  )
  expect_equal(
  mean(ProjectField(dat2, eof2, mode = 6)),
  0.1741076,
  tolerance = 0.0001
  )

})

##############################################
test_that("4. dat3", {
  expect_equal(
  dim(ProjectField(dat3, eof3)),
  c(sdate = 6, dat = 1, memb = 1, ftime = 1)
  )
  expect_equal(
  ProjectField(dat3, eof3)[1:6],
  c(NA, 0, 0, 0, 0, 0),
  tolerance = 0.0001
  )

})
##############################################
test_that("5. dat4", {
  expect_equal(
  dim(ProjectField(dat4, eof4)),
  c(sdate = 6, dat = 1, memb = 2, ftime = 3)
  )
  expect_equal(
  mean(ProjectField(dat4, eof4)),
  -0.1179755,
  tolerance = 0.0001
  )
  expect_equal(
  ProjectField(dat4, eof4)[, 1, 2, 2],
  c(1.73869255, -2.58156427, 0.05340228, -0.53610350, -3.13985059, 1.58785066),
  tolerance = 0.0001
  )

})
##############################################
