context("CSTools::CST_RFTemp tests")

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

# dat1
data <- rnorm(2 * 10 * 4 * 5 * 6 * 7)
dim(data) <- c(dataset = 2, member = 10,
                sdate = 4, ftime = 5, lat = 6, lon = 7)
lon <- seq(0, 12, 2)
lat <- seq(10, 15, 1)
coords <- list(lon = lon, lat = lat)
exp1 <- list(data = data, coords = coords)
attr(exp1, "class") <- "s2dv_cube"

# dat2
exp2 <- exp1
exp2$attrs <- list(source_files = 'exp')
exp2$coords <- NULL
exp2_2 <- exp2
exp2_2$coords <- list(long = seq(1:4), lati = seq(1:4))

# dat
t <- rnorm(2 * 6 * 6 * 2 * 3 * 4) * 10 + 273.15 + 10
dim(t) <- c(dataset = 2, member = 2, sdate = 3, ftime = 4, lat = 6, lon = 6)
lon <- seq(4, 9, 1)
lat <- seq(42, 47, 1)
coords <- list(lon = lon, lat = lat)
exp <- list(data = t, coords = coords)
attr(exp, "class") <- "s2dv_cube"
o <- runif(29 * 29) * 3000
dim(o) <- c(lat = 29, lon = 29)
lon <- seq(3.125, 10.125, 0.25) - 100
lat <- seq(41.125, 48.125, 0.25) - 60
coords <- list(lon = lon, lat = lat)
oro1 <- list(data = o, coords = coords)
attr(oro1, "class") <- "s2dv_cube"

oro <- oro1
oro$coords$lon <- oro$coords$lon + 100
oro$coords$lat <- oro$coords$lat + 60

##############################################
test_that("1. Input checks", {
  # Check 's2dv_cube'
  expect_error(
    CST_RFTemp(rnorm(2 * 15 * 4 * 5 * 6 * 7)),
    paste0("Parameter 'data' must be of the class 's2dv_cube', ",
           "as output by CSTools::CST_Load.")
  )
  expect_error(
    CST_RFTemp(data = exp1, oro = rnorm(2 * 15 * 4 * 5 * 6 * 7)),
    paste0("Parameter 'oro' must be of the class 's2dv_cube', ",
           "as output by CSTools::CST_Load.")
  )
  expect_error(
    CST_RFTemp(data = exp1, oro = exp1, delta = rnorm(2 * 15 * 4 * 5 * 6 * 7)),
    paste0("Parameter 'delta' must be of the class 's2dv_cube', ",
           "as output by CSTools::CST_Load.")
  )
  # Check 's2dv_cube' structure
  expect_error(
    CST_RFTemp(exp2, oro = exp1),
    paste0("Parameter 'data' must have 'data' and 'coords' elements ",
           "within the 's2dv_cube' structure.")
  )
  expect_error(
    CST_RFTemp(oro = exp2, data = exp1),
    paste0("Parameter 'oro' must have 'data' and 'coords' elements ",
           "within the 's2dv_cube' structure.")
  )
  # Check coordinates
  expect_error(
    CST_RFTemp(exp2_2, oro = exp1),
    paste0("Spatial coordinate names of 'data' do not match any of the names ",
           "accepted by the package.")
  )
  expect_error(
    CST_RFTemp(exp1, oro = exp2_2),
    paste0("Spatial coordinate names of 'oro' do not match any of the names ",
           "accepted by the package.")
  )
  expect_error(
    res <- CST_RFTemp(exp, oro1, xlim = c(1, 3), ylim = c(1, 3), time_dim = 'ftime'),
    "Orography not available for selected area"
  )
  expect_error(
    res <- CST_RFTemp(exp, oro, xlim = c(3, 8), ylim = c(43, 46), time_dim = 'ftime'),
    "Downscaling area not contained in input data"
  )
})

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

test_that("2. Output checks", {
  expect_warning(
    resl <- CST_RFTemp(exp, oro, lapse = 6.5),
    "Selected time dim: ftime"
  )

  dimexp <- dim(exp$data)
  expect_equal(dim(resl$data), c(lon = 16, lat = 16, dimexp["ftime"],
                                dimexp["sdate"], dimexp["dataset"],
                                dimexp["member"]))
  expect_warning(
  resd <- CST_RFTemp(exp, oro, time_dim = c("ftime", "sdate", "member"),
                      nolapse = TRUE), NA)
  dim(resd$data) <- c(16, 16, 4 * 3 * 2 * 2)
  resm <- apply(resd$data, c(1, 2), mean)
  expect_equal(mean(oro$data[7:22, 7:22]), mean(resm), tolerance = 1e-10)

  # Test precomputation of delta based with nolapse
  delta <- CST_RFTemp(exp, oro, time_dim = c("ftime", "sdate", "member"),
                      nolapse = TRUE, compute_delta = TRUE)
  resdnl <- CST_RFTemp(exp, oro, time_dim = c("ftime", "sdate", "member"),
                       nolapse = TRUE, delta = delta)
  expect_equal(mean(resdnl$data), mean(resd$data), tolerance = 1e-10)

  # Test precomputation of delta based with lapse rate
  delta <- CST_RFTemp(exp, oro, time_dim = c("ftime", "sdate", "member"),
                      lapse = 6.5, compute_delta = TRUE)
  resdl <- CST_RFTemp(exp, oro, time_dim = c("ftime", "sdate", "member"),
                      delta = delta)
  expect_equal(mean(resdl$data), mean(resl$data), tolerance = 1e-10)

  expect_warning(
  resd <- CST_RFTemp(exp, oro, time_dim = c("ftime", "sdate", "member"),
                      nolapse = TRUE, method = "nearest"), NA)
  dim(resd$data) <- c(16, 16, 4 * 3 * 2 * 2)
  resm <- apply(resd$data, c(1, 2), mean)
  expect_equal(mean(oro$data[7:22, 7:22]), mean(resm), tolerance = 1e-10)
})
