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

# cube1
cube1 <- NULL
cube1$data <- array(rnorm(10), dim = c(lat = 2, time = 5))
class(cube1) <- 's2dv_cube'

# cube2
cube2 <- NULL
cube2$data <- array(rnorm(10), dim = c(lat = 2, time = 5))
class(cube2) <- 's2dv_cube'
cube2$coords <- list(lat = 1:2)

# dat1
dims <- c(syear = 6, time = 3, latitude = 2, longitude = 1, ensemble = 10)

set.seed(1)
exp_tasmax <- array(rnorm(360, 27.73, 5.26), dim = dims)
set.seed(2)
exp_tasmin <- array(rnorm(360, 14.83, 3.86), dim = dims)
set.seed(3)
exp_prlr <- array(rnorm(360, 21.19, 25.64), dim = dims)

dates_exp <- as.Date(c(paste0(2010:2015, "-08-16"), paste0(2010:2015, "-09-15"), 
                       paste0(2010:2015, "-10-16")))
dim(dates_exp) <- c(syear = 6, time = 3)

lat <- c(40,40.1)

exp1 <- list('tmax' = exp_tasmax, 'tmin' = exp_tasmin, 'pr' = exp_prlr)

# dat2
dims2 <- c(styear = 6, ftime = 3, lat = 2, lon = 1, member = 10)

set.seed(1)
exp_tas <- array(rnorm(100, 17.34, 9.18), dim = dims2)
set.seed(2)
exp_prlr <- array(rnorm(360, 21.19, 25.64), dim = dims2)

dates_exp2 <- as.Date(c(paste0(2010:2015, "-08-16"), paste0(2010:2015, "-09-15"), 
                       paste0(2010:2015, "-10-16")))
dim(dates_exp2) <- c(sday = 1, sweek = 1, styear = 6, ftime = 3)

lat <- c(40,40.1)

exp2 <- list('tmean' = exp_tas, 'pr' = exp_prlr)

# cube4
cube4_exp <- lapply(exp1, function(x) {
  suppressWarnings(
    CSTools::s2dv_cube(data = x, coords = list(latitude = c(40, 40.1)), 
                       varName = 'test', Dates = as.POSIXct(dates_exp))
  )
})

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

test_that("1. Initial checks CST_PeriodPET", {
  # Check 's2dv_cube'
  expect_error(
    CST_PeriodPET(data = NULL), 
    "Parameter 'data' cannot be NULL."
  )
  expect_error(
    CST_PeriodPET(data = array(10)), 
    "Parameter 'data' must be a list of 's2dv_cube' class."
  )
  # latitude
  expect_error(
    CST_PeriodPET(data = list(cube1)), 
    paste0("Spatial coordinate names of parameter 'data' do not match any ",
           "of the names accepted by the package.")
  )
  # Dates
  expect_error(
    CST_PeriodPET(data = list(cube2)),
    paste0("Element 'Dates' is not found in 'attrs' list of 'data'. ", 
           "See 's2dv_cube' object description in README file for more ", 
           "information.")
  )
})

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

test_that("1. Initial checks PeriodPET", {
  # data
  expect_error(
    PeriodPET(data = NULL), 
    "Parameter 'data' needs to be a named list with the needed variables."
  )
  expect_error(
    PeriodPET(data = list(1)), 
    "Parameter 'data' needs to be a named list with the variable names."
  )
  expect_error(
    PeriodPET(data = list(tasmax = array(10))), 
    "Parameter 'data' needs to be a list of arrays with dimension names."
  )
  expect_error(
    PeriodPET(data = list(tasmax = array(10, c(time = 10)), 
                          tasmin = array(10, c(time = 11)))),
    "Parameter 'data' variables need to have the same dimensions."
  )
  expect_error(
    PeriodPET(data = list(tasmax = array(10, c(time = 10)), 
                          tasmin = array(10, c(ftime = 10)))),
    "Parameter 'data' variables need to have the same dimensions."
  )
  # lat
  expect_error(
    PeriodPET(data = exp1, lat = 'lat'),
    "Parameter 'lat' must be numeric."
  )
  expect_error(
    PeriodPET(data = list(tasmax = array(10, c(time = 10)), 
                          tasmin = array(10, c(time = 10))), lat = 1:2),
    "Parameter 'data' must have 'lat_dim' dimension."
  )
  # data (2)
  expect_warning(
    PeriodPET(data = exp1, pet_method = '1', dates = dates_exp, lat = lat), 
    paste0("Parameter 'pet_method' needs to be 'hargreaves' or ", 
           "'hargreaves_modified'. It is set to 'hargreaves_modified'.")
  )
  # time_dim
  expect_error(
    PeriodPET(data = exp1, time_dim = 1, dates = dates_exp, lat = lat),
    "Parameter 'time_dim' must be a character string."
  )
  expect_error(
    PeriodPET(data = exp2, lat = lat, dates = dates_exp2, 
              lat_dim = 'lat', pet_method = 'thornthwaite'),
    "Parameter 'time_dim' is not found in 'data' dimension."
  )
  # leadtime_dim
  expect_error(
    PeriodPET(data = exp1, leadtime_dim = 1, dates = dates_exp, lat = lat),
    "Parameter 'leadtime_dim' must be a character string."
  )
  expect_error(
    PeriodPET(data = exp2, lat = lat, dates = dates_exp2, 
               lat_dim = 'lat', time_dim = 'ftime', pet_method = 'thornthwaite'),
    "Parameter 'leadtime_dim' is not found in 'data' dimension."
  )
  # lat_dim
  expect_error(
    PeriodPET(data = exp1, lat_dim = 1, dates = dates_exp, lat = lat)
  )
  expect_error(
    PeriodPET(data = exp2, lat = lat, dates = dates_exp2),
    "Parameter 'data' must have 'lat_dim' dimension."
  )
  # na.rm
  expect_error(
    PeriodPET(data = exp1, na.rm = 1.5, dates = dates_exp, lat = lat),
    "Parameter 'na.rm' must be one logical value."
  )
  # ncores
  expect_error(
    PeriodPET(data = exp1, ncores = 1.5, dates = dates_exp, lat = lat),
    "Parameter 'ncores' must be a positive integer."
  ) 
})

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

test_that("2. Output checks", {
  res01 <- CST_PeriodPET(data = cube4_exp)
  res1 <- PeriodPET(data = exp1, lat = lat, dates = dates_exp)
  res2 <- PeriodPET(data = exp2, lat = lat, dates = dates_exp2, 
                    pet_method = c('thornthwaite'), 
                    lat_dim = 'lat', time_dim = 'styear', 
                    leadtime_dim = 'ftime')
  # structure
  expect_equal(
    names(res01),
    c('data', 'dims', 'coords', 'attrs')
  )
  # dims
  expect_equal(
    dim(res1),
    c(syear = 6, time = 3, latitude = 2, longitude = 1, ensemble = 10)
  )
  # values
  expect_equal(
    res1[1:4],
    c(137.77342, 154.55548, 65.72859, 222.20438),
    tolerance = 0.0001
  )
  expect_equal(
    res2[1:4],
    c(77.76124, 118.94212, 66.57568, 185.67074),
    tolerance = 0.0001
  )
})

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