context("s2dv::REOF 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)

  # dat2
  set.seed(2)
  dat2 <- array(rnorm(120), dim = c(dat = 2, lat = 6, lon = 2, sdate = 5))
  lat2 <- lat1
  lon2 <- lon1

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

  # ano
  expect_error(
  REOF(c()),
  "Parameter 'ano' cannot be NULL."
  )
  expect_error(
    REOF(c(NA, NA)),
    "Parameter 'ano' must be a numeric array."
  )
  expect_error(
    REOF(list(a = array(rnorm(50), dim = c(dat = 5, sdate = 10)), b = c(1:4))),
    "Parameter 'ano' must be a numeric array."
  )
  expect_error(
    REOF(array(1:10, dim = c(2, 5))),
    "Parameter 'ano' must have dimension names."
  )
  # time_dim
  expect_error(
    REOF(dat1, time_dim = 2),
    "Parameter 'time_dim' must be a character string."
  )
  expect_error(
    REOF(dat1, time_dim = c('a','sdate')),
    "Parameter 'time_dim' must be a character string."
  )
  # space_dim
  expect_error(
    REOF(dat1, space_dim = 'lat'),
    "Parameter 'space_dim' must be a character vector of 2."
  )
  expect_error(
    REOF(dat1, space_dim = c('latitude', 'longitude')),
    "Parameter 'space_dim' is not found in 'ano' dimension."
  )
  # lat
  expect_error(
    REOF(dat1, lat = 1:10),
    paste0("Parameter 'lat' must be a numeric vector with the same ",
                "length as the latitude dimension of 'ano'.")
  )
  expect_error(
    REOF(dat1, lat = seq(-100, -80, length.out = 6)),
    "Parameter 'lat' must contain values within the range \\[-90, 90\\]."
  )
  # lon
  expect_error(
    REOF(dat1, lat = lat1, lon = c('a', 'b')),
    paste0("Parameter 'lon' must be a numeric vector with the same ",
                "length as the longitude dimension of 'ano'.")
  )
  expect_error(
    REOF(dat1, lat = lat1, lon = c(350, 370)),
    "Parameter 'lon' must be within the range [-180, 180] or [0, 360].",
    fixed = TRUE 
  )
  # ntrunc
  expect_error(
    REOF(dat1, lat = lat1, lon = lon1, ntrunc = 0),
    "Parameter 'ntrunc' must be a positive integer."
  )
  # corr
  expect_error(
    REOF(dat1, lat = lat1, lon = lon1, corr = 0.1),
    "Parameter 'corr' must be one logical value."
  )
  # ncores
  expect_error(
    REOF(dat1, lat1, lon1, ncore = 3.5),
    "Parameter 'ncores' must be a positive integer."
  )

})

##############################################
test_that("2. dat1", {
  expect_warning(
  REOF(dat1, lon = lon1, lat = lat1),
  "Parameter 'ntrunc' is changed to 10, the minimum among the length of time_dim, the production of the length of space_dim, and ntrunc.",
  fixed = TRUE
  )
  expect_equal(
  names(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 10)),
  c("REOFs", "RPCs", "var", "wght")
  )
  expect_equal(
  dim(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 10)$REOFs),
  c(mode = 10, lat = 6, lon = 2)
  )
  expect_equal(
  dim(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 9)$RPCs),
  c(sdate = 10, mode = 9)
  )
  expect_equal(
  dim(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 1)$var),
  c(mode = 1)
  )
  expect_equal(
  dim(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 1)$wght),
  c(lat = 6, lon = 2)
  )
  expect_equal(
  REOF(dat1, lon = lon1, lat = lat1, ntrunc = 1)$REOFs[1:5],
  c(-0.28881677, 0.47116712, 0.27298759, 0.32794052, 0.01873475),
  tolerance = 0.0001
  )
  expect_equal(
  mean(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 2)$REOFs),
  -0.007620167,
  tolerance = 0.0001
  )
  expect_equal(
  REOF(dat1, lon = lon1, lat = lat1, ntrunc = 2)$RPCs[4:8],
  c(-0.58817084, -1.86745710, -0.09939452, -1.11012382, 1.89513430),
  tolerance = 0.0001
  )
  expect_equal(
  REOF(dat1, lon = lon1, lat = lat1, ntrunc = 2)$var[1:2],
  array(c(28.04203, 26.56988), dim = c(mode = 2)),
  tolerance = 0.0001
  )
  expect_equal(
  REOF(dat1, lon = lon1, lat = lat1, ntrunc = 1)$wght[1,1],
  REOF(dat1, lon = lon1, lat = lat1, ntrunc = 1)$wght[1,2]
  )
  expect_equal(
  REOF(dat1, lon = lon1, lat = lat1, ntrunc = 1)$wght[1:1],
  c(0.9923748),
  tolerance = 0.0001
  )

})
##############################################
test_that("3. dat2", {
  expect_equal(
  dim(REOF(dat2, lon = lon2, lat = lat2, ntrunc = 5)$REOFs),
  c(mode = 5, lat = 6, lon = 2, dat = 2)
  )
  expect_equal(
  dim(REOF(dat2, lon = lon2, lat = lat2, ntrunc = 4)$RPCs),
  c(sdate = 5, mode = 4, dat = 2)
  )
  expect_equal(
  dim(REOF(dat2, lon = lon2, lat = lat2, ntrunc = 2)$wght),
  c(lat = 6, lon = 2)
  )
  expect_equal(
  REOF(dat2, lon = lon2, lat = lat2, ntrunc = 1)$REOFs[1, 3, 2, 1],
  0.09529009,
  tolerance = 0.0001
  )
  expect_equal(
  mean(REOF(dat2, lon = lon2, lat = lat2, ntrunc = 5)$REOFs),
  0.01120786,
  tolerance = 0.0001
  )

})

