context("s2dv::GMST 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))
 mask_sea_land <- array(c(1, 0, 1), dim = c(lat = 19, lon = 37))
 sea_value <- 1

## Observations or reanalyses
 dat_tas1 <- array(1:100, dim = c(year = 5, lat = 19, lon = 37, month = 12))
 dat_tos1 <- array(2:101, dim = c(year = 5, lat = 19, lon = 37, month = 12))

 ## Historical simulations
 dat_tas2 <- array(1:100, dim = c(year = 5, lat = 19, lon = 37, month = 12, member = 5))
 dat_tos2 <- array(2:101, dim = c(year = 5, lat = 19, lon = 37, month = 12, member = 5))

 ## Decadal predictions
 dat_tas3 <- array(1:100, dim = c(sdate = 5, lat = 19, lon = 37, fmonth = 24, member = 5))
 dat_tos3 <- array(2:101, dim = c(sdate = 5, lat = 19, lon = 37, fmonth = 24, member = 5))

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

  expect_error(
  GMST(data_tas = c(), data_tos = c()),
  "Parameter 'data_tas' and 'data_tos' cannot be NULL."
  )
  expect_error(
  GMST(data_tas = 'a', data_tos = dat_tos1),
  "Parameter 'data_tas' and 'data_tos' must be a numeric array."
  )
  expect_error(
  GMST(data_tas = dat_tas1, data_tos = dat_tos2),
  "The dimension of data_tas and data_tos must be identical."
  )
  expect_error(
  GMST(data_tas = dat_tas1, data_tos = dat_tos1, data_lats = c()),
  "Parameter 'data_lats' must be a numeric vector."
  )
  expect_error(
  GMST(data_tas = dat_tas1, data_tos = dat_tos1, data_lats = lat, data_lons = c()),
  "Parameter 'data_lons' must be a numeric vector."
  )
  expect_error(
  GMST(data_tas = dat_tas1, data_tos = dat_tos1, data_lats = lat, data_lons = lon,
       sea_value = sea_value, mask_sea_land = TRUE),
  "Parameter 'mask_sea_land' must be an array with dimensions \\[lat_dim, lon_dim\\]."
  )
  expect_error(
  GMST(data_tas = dat_tas1, data_tos = dat_tos1, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = TRUE),
  "Parameter 'sea_value' must be a numeric value."
  )
  expect_error(
  GMST(data_tas = dat_tas1, data_tos = dat_tos1, data_lats = lat, data_lons = lon, 
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = TRUE),
  "Parameter 'type' must be 'dcpp', 'hist', or 'obs'."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon, 
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp', 
       lat_dim = 2),
  "Parameter 'lat_dim' must be a character string."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp', 
       lat_dim = 'lats'),
  "Parameter 'lat_dim' is not found in 'data_tas' or 'data_tos' dimension."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp', 
       lon_dim = 2),
  "Parameter 'lon_dim' must be a character string."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp', 
       lon_dim = 'lons'),
  "Parameter 'lon_dim' is not found in 'data_tas' or 'data_tos' dimension."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = seq(-90, 90, 11), data_lons = lon, mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp'),
  paste0("The latitude dimension of parameter 'data_tas' and 'data_tos'",
         " must be the same length of parameter 'data_lats'.")
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = c(1:10), 
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp'),
  paste0("The longitude dimension of parameter 'data_tas' and 'data_tos'",
         " must be the same length of parameter 'data_lons'.")
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon, 
       mask_sea_land = mask_sea_land, sea_value = sea_value, 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(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon, 
       mask_sea_land = mask_sea_land, sea_value = sea_value, 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(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon, 
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
       monini = 0),
  "Parameter 'monini' must be an integer from 1 to 12."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
       fmonth_dim = c('lat', 'lon')),
  "Parameter 'fmonth_dim' must be a character string."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
       fmonth_dim = 'asd'),
  "Parameter 'fmonth_dim' is not found in 'data_tas' or 'data_tos' dimension."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
       sdate_dim = 2),
  "Parameter 'sdate_dim' must be a character string."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
       sdate_dim = 'date'),
  "Parameter 'sdate_dim' is not found in 'data_tas' or 'data_tos' dimension."
  )
  expect_error(
  GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, 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(
  GMST(data_tas = dat_tas2, data_tos = dat_tos2, data_lats = lat, data_lons = lon, 
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'hist',
       year_dim = 1),
  "Parameter 'year_dim' must be a character string."
  )
  expect_error(
  GMST(data_tas = dat_tas2, data_tos = dat_tos2, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'hist',
       year_dim = 'yr'),
  "Parameter 'year_dim' is not found in 'data_tas' or 'data_tos' dimension."
  )
  expect_error(
  GMST(data_tas = dat_tas2, data_tos = dat_tos2, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'hist',
       month_dim = 0),
  "Parameter 'month_dim' must be a character string."
  )
  expect_error(
  GMST(data_tas = dat_tas2, data_tos = dat_tos2, data_lats = lat, data_lons = lon,
       mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'hist',
       month_dim = 'mth'),
  "Parameter 'month_dim' is not found in 'data_tas' or 'data_tos' dimension."
  )

})

##############################################
test_that("2. Output checks: dat1", {
 res1_1 <- GMST(data_tas = dat_tas1, data_tos = dat_tos1, data_lats = lat, data_lons = lon, 
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'obs')

 expect_equal(
 dim(res1_1),
 c(year = 5)
 )
 expect_equal(
 res1_1,
 array(seq(-2, 2, 1), dim = c(year = 5))
 )

 res1_2 <- GMST(data_tas = dat_tas1, data_tos = dat_tos1, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'obs',
               indices_for_clim = F)
 expect_equal(
 mean(res1_2),
 51.09007,
 tolerance = 0.00001
 )

})
##############################################
test_that("3. Output checks: dat2", {
 res2_1 <- GMST(data_tas = dat_tas2, data_tos = dat_tos2, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'hist')
 expect_equal(
 dim(res2_1),
 c(year = 5, member = 5)
 )
 expect_equal(
 mean(res2_1),
 0
 ) 
 expect_equal(
 range(res2_1),
 c(-2, 2),
 tolerance = 0.00001
 )

 res2_2 <- GMST(data_tas = dat_tas2, data_tos = dat_tos2, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'hist',
               indices_for_clim = 2:3)
 expect_equal(
 mean(res2_2),
 0.5
 )

 res2_3 <- GMST(data_tas = dat_tas2, data_tos = dat_tos2, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'hist',
                mask = mask)
 expect_equal(
 mean(res2_3)*10^16,
 0,
 tolerance = 0.00001
 )

})
##############################################
test_that("4. Output checks: dat3", {
 res3_1 <- GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp')
 expect_equal(
 dim(res3_1),
 c(fyear = 1, sdate = 5, member = 5)
 )
 expect_equal(
 mean(res3_1)*10^16,
 -2.842084,
 tolerance = 0.00001
 )

 res3_2 <- GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
                indices_for_clim = 2:3)
 expect_equal(
 mean(res3_2),
 0.5
 )

 res3_3 <- GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
                monini = 10)
 expect_equal(
 mean(res3_3),
 0
 )

 res3_4 <- GMST(data_tas = dat_tas3, data_tos = dat_tos3, data_lats = lat, data_lons = lon,
                mask_sea_land = mask_sea_land, sea_value = sea_value, type = 'dcpp',
                mask = mask)
 expect_equal(
 mean(res3_4)*10^16,
 -5.684949,
 tolerance = 0.00001
 )

})
