context("CSTools::CST_Analogs tests")

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

# dat1
exp1 <- rnorm(1:20)
dim(exp1) <- c(lat = 4, lon = 5)

obs1 <- c(rnorm(1:180), exp1 * 1.2)
dim(obs1) <- c(time = 10, lat = 4, lon = 5)

time_obsL1 <- paste(rep("01", 10), rep("01", 10), 1994 : 2003, sep = "-")
time_expL1 <- "01-01-1994"
lon1 <- seq(0, 20, 5)
lat1 <- seq(0, 15, 4)
coords = list(lat = lat1, lon = lon1)
attrs_expL <- list(Dates = time_expL1)
attrs_obsL <- list(Dates = time_obsL1)
exp <- list(data = exp1, coords = coords, attrs = attrs_expL)
obs <- list(data = obs1, coords = coords, attrs = attrs_obsL)
attr(exp, 'class') <- 's2dv_cube'
attr(obs, 'class') <- 's2dv_cube'

# dat2
obs2 <- obs
obs2$coords <- NULL
obs2_2 <- obs2
obs2_2$coords <- list(long = seq(1:4), lati = seq(1:4))

##############################################
test_that("1. Input checks: CST_Analogs", {
  # Check 's2dv_cube'
  expect_error(
    CST_Analogs(expL = 1, obsL = 1),
    paste0("Parameter 'expL' and 'obsL' must be of the class 's2dv_cube', ",
           "as output by CSTools::CST_Load.")
  )
  expect_error(
    CST_Analogs(expL = exp, obsL = obs, expVar = 1),
    paste0("Parameter 'expVar' must be of the class 's2dv_cube', ",
           "as output by CSTools::CST_Load.")
  )
  expect_error(
    CST_Analogs(expL = exp, obsL = obs, obsVar = 1),
    paste0("Parameter 'obsVar' must be of the class 's2dv_cube', ",
           "as output by CSTools::CST_Load.")
  )

  # Check 'obsL' object structure
  expect_error(
    CST_Analogs(expL = exp, obsL = obs2),
    paste0("Parameter 'obsL' must have 'data', 'coords' and 'attrs' elements ",
           "within the 's2dv_cube' structure.")
  )
  expect_error(
    CST_Analogs(expL = exp, obsL = obs2_2),
    paste0("Spatial coordinate names of parameter 'obsL' do not match any ",
           "of the names accepted by the package.")
  )
  # Check 'obsVar' object structure
  expect_error(
    CST_Analogs(expL = exp, obsL = obs, expVar = exp, obsVar = obs2),
    paste0("Parameter 'obsVar' must have 'data', 'coords' and 'attrs' elements ",
           "within the 's2dv_cube' structure.")
  )
  expect_error(
    CST_Analogs(expL = exp, obsL = obs, expVar = exp, obsVar = obs2_2),
    paste0("Spatial coordinate names of parameter 'obsVar' do not match any ",
           "of the names accepted by the package.")
  )
})

##############################################
test_that("2. Input checks: Analogs", {
  # expL, obsL
  expect_error(
    Analogs(expL = 1),
    "Parameter 'expL' must be a numeric array."
  )
  expect_error(
    Analogs(expL = exp1, obsL = 1),
    "Parameter 'obsL' must be a numeric array."
  )
  expect_error(
    Analogs(expL = array(1:10), obsL = obs1),
    "Parameter 'expL' must have dimension names."
  )
  expect_error(
    Analogs(expL = exp1, obsL = array(1:10)),
    "Parameter 'obsL' must have dimension names."
  )
  exp$data[1, 2] <- NA
  expect_warning(
    Analogs(expL = exp$data, obsL = obs1, time_obsL = time_obsL1, 
            time_expL = time_expL1),
    "Parameter 'expL' contains NA values."
  )
  expect_error(
    Analogs(expL = array(1:10, dim = c(time = 10)), obsL = obs1),
    "Parameter 'expL' and 'obsL' must have longitudinal dimension."
  )
  expect_error(
    Analogs(expL = exp1, obsL = array(1:10, dim = c(lon = 10))),
    "Parameter 'expL' and 'obsL' must have latitudinal dimension."
  )
  # criteria
  expect_error(
    Analogs(expL = exp1, obsL = obs1, criteria = 1),
    "Parameter 'criteria' can only be: 'Large_dist', 'Local_dist' or 'Local_cor'."
  )
  # lonL, latL, lonVar, latVar
  expect_error(
    Analogs(expL = exp1, obsL = obs1, criteria = "Local_dist"),
    "Parameters 'lonL' and 'latL' cannot be NULL."
  )
  expect_error(
    Analogs(expL = exp1, obsL = obs1, criteria = "Local_dist", lonL = 'a', latL = 'b'),
    "Parameters 'lonL' and 'latL' must be numeric."
  )
  expect_error(
    Analogs(expL = exp1, obsL = obs1, criteria = "Local_cor", 
            lonL = array(1:10, dim = c(2,5)), latL = lat1),
    "Parameters 'lonL' and 'latL' need to be a vector."
  )
  suppressWarnings(
    expect_error(
      Analogs(expL = exp1, obsL = obs1, criteria = "Local_cor", lonL = lon1, 
              time_expL = time_expL1, time_obsL = NULL, latL = lat1),
      "Parameters 'lonVar' and 'latVar' cannot be NULL."
    )
  )
  suppressWarnings(
    expect_error(
      Analogs(expL = exp1, obsL = obs1, criteria = "Local_cor", lonL = lon1, 
              time_obsL = time_obsL1, latL = lat1, lonVar = lon1, latVar = lat1),
      "Parameter 'time_expL' cannot be NULL."
    )
  )
})

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

test_that("3. Output checks" , {
  suppressWarnings(
    res <- CST_Analogs(expL = exp, obsL = obs)
  )
  expect_equal(
    names(res),
    c('data', 'coords', 'attrs')
  )
  expect_equal(
    dim(res$data),
    c(nAnalogs = 1,  lat = 4, lon = 5)
  )
  suppressWarnings(
    res1 <- CST_Analogs(expL = exp, obsL = obs, expVar = exp, obsVar = obs, 
                        AnalogsInfo = TRUE)
  )
  expect_equal(
    names(res1$data),
    c('fields', 'analogs', 'metric', 'dates')
  )
  expect_equal(
    dim(res1$data$fields),
    c(nAnalogs = 1, lat = 4, lon = 5)
  )
})
