context("s2dv::AMV tests")

##############################################
 lat <- seq(-90, 90, 10)
 lon <- seq(0, 360, 10)
 set.seed(1)
 mask <- array(sample(c(0, 1), 19*37, replace = T), dim = c(lat = 19, lon = 37))

## Observations or reanalyses
 dat1 <- array(1:100, dim = c(year = 5, lat = 19, lon = 37, month = 12))
 
 ## Historical simulations
 dat2 <- array(1:100, dim = c(year = 5, lat = 19, lon = 37, month = 12, member = 5))
 
 ## Decadal predictions
 dat3 <- array(1:100, dim = c(sdate = 5, lat = 19, lon = 37, fmonth = 24, member = 5))

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

  expect_error(
  AMV(data = c()),
  "Parameter 'data' cannot be NULL."
  )
  expect_error(
  AMV(data = 'a'),
  "Parameter 'data' must be a numeric array."
  )
  expect_error(
  AMV(data = dat1, data_lats = c()),
  "Parameter 'data_lats' must be a numeric vector."
  )
  expect_error(
  AMV(data = dat1, data_lats = lat, data_lons = c()),
  "Parameter 'data_lons' must be a numeric vector."
  )
  expect_error(
  AMV(data = dat1, data_lats = lat, data_lons = lon, type = TRUE),
  "Parameter 'type' must be 'dcpp', 'hist', or 'obs'."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      lat_dim = 2),
  "Parameter 'lat_dim' must be a character string."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      lat_dim = 'lats'),
  "Parameter 'lat_dim' is not found in 'data' dimension."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      lon_dim = 2),
  "Parameter 'lon_dim' must be a character string."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      lon_dim = 'lons'),
  "Parameter 'lon_dim' is not found in 'data' dimension."
  )
  expect_error(
  AMV(data = dat3, data_lats = seq(-90, 90, 11), data_lons = lon, type = 'dcpp'),
  paste0("The latitude dimension of parameter 'data' must be the same",
         " length of parameter 'data_lats'.")
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = c(1:10), type = 'dcpp'),
  paste0("The longitude dimension of parameter 'data' must be the same",
         " length of parameter 'data_lons'.")
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      mask = c(1, 0, 1, 0, 0)),
  paste0("Parameter 'mask' must be NULL \\(no mask\\) or a numerical array ",
         "with c\\(lat_dim, lon_dim\\) dimensions and 0 in those grid ",
         "points that have to be masked.")
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      mask = array(rep(c(1, 0), 100), dim = c(lat = 20, lon = 5))),
  paste0("Parameter 'mask' must be NULL \\(no mask\\) or a numerical array ",
         "with c\\(lat_dim, lon_dim\\) dimensions and 0 in those grid ",
         "points that have to be masked.")
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      monini = 0),
  "Parameter 'monini' must be an integer from 1 to 12."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      fmonth_dim = c('lat', 'lon')),
  "Parameter 'fmonth_dim' must be a character string."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      fmonth_dim = 'asd'),
  "Parameter 'fmonth_dim' is not found in 'data' dimension."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      sdate_dim = 2),
  "Parameter 'sdate_dim' must be a character string."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      sdate_dim = 'date'),
  "Parameter 'sdate_dim' is not found in 'data' dimension."
  )
  expect_error(
  AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
      indices_for_clim = TRUE),
  paste0("The parameter 'indices_for_clim' must be a numeric vector ",
         "or NULL to compute the anomalies based on the whole period, ",
         "or FALSE if data are already anomalies")
  )
  expect_error(
  AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
      year_dim = 1),
  "Parameter 'year_dim' must be a character string."
  )
  expect_error(
  AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
      year_dim = 'yr'),
  "Parameter 'year_dim' is not found in 'data' dimension."
  )
  expect_error(
  AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
      month_dim = 0),
  "Parameter 'month_dim' must be a character string."
  )
  expect_error(
  AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
      month_dim = 'mth'),
  "Parameter 'month_dim' is not found in 'data' dimension."
  )
  expect_error(
  AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
      member_dim = 1),
  "Parameter 'member_dim' must be a character string."
  )
  expect_error(
  AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
      member_dim = 'ens'),
  "Parameter 'member_dim' is not found in 'data' dimension."
  )

})

##############################################
test_that("2. Output checks: dat1", {
 res1_1 <- AMV(data = dat1, data_lats = lat, data_lons = lon, type = 'obs')

 expect_equal(
 dim(res1_1),
 c(year = 5)
 )
 expect_equal(
 mean(res1_1)*10^17,
 -4.440892,
 tolerance = 0.00001
 )

 res1_2 <- AMV(data = dat1, data_lats = lat, data_lons = lon, type = 'obs',
               indices_for_clim = F)
 expect_equal(
 mean(res1_2),
 -1.78994,
 tolerance = 0.00001
 )

})
##############################################
test_that("3. Output checks: dat2", {
 res2_1 <- AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist')
 expect_equal(
 dim(res2_1),
 c(year = 5, member = 5)
 )
 expect_equal(
 mean(res2_1)*10^17,
 -3.549383,
 tolerance = 0.00001
 ) 

 res2_2 <- AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
               indices_for_clim = 2:3)
 expect_equal(
 mean(res2_2)*10^16,
 8.616545,
 tolerance = 0.00001
 )

 res2_3 <- AMV(data = dat2, data_lats = lat, data_lons = lon, type = 'hist',
               mask = mask)
 expect_equal(
 mean(res2_3)*10^17,
 -4.437162,
 tolerance = 0.00001
 )

})
##############################################
test_that("4. Output checks: dat3", {
 res3_1 <- AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp')
 expect_equal(
 dim(res3_1),
 c(fyear = 1, sdate = 5, member = 5)
 )
 expect_equal(
 mean(res3_1)*10^18,
 -8.881784,
 tolerance = 0.00001
 )

 res3_2 <- AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
               indices_for_clim = 2:3)
 expect_equal(
 mean(res3_2)*10^16,
 8.459899,
 tolerance = 0.00001
 )

 res3_3 <- AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
               monini = 5)
 expect_equal(
 mean(res3_3)*10^17,
 -4.884981,
 tolerance = 0.00001
 )

 res3_4 <- AMV(data = dat3, data_lats = lat, data_lons = lon, type = 'dcpp',
               mask = mask)
 expect_equal(
 mean(res3_4)*10^17,
 2.220446,
 tolerance = 0.00001
 )

})
