# This unit test tests the chunking over depended and depending dimension.
# ex1_14
# 1. depending dim is values()
# 2. depending dim is indices()
#   a. depended dim is indices()
#   b. depended dim is list of values
# Note that 2.b. doesn't work.

context("Chunk over dimensions that have dependency relationship")

path <- paste0('/esarchive/exp/CMIP6/dcppA-hindcast/HadGEM3-GC31-MM/DCPP/MOHC/',
               'HadGEM3-GC31-MM/dcppA-hindcast/',
               'r1i1p1f2/Omon/tos/gn/v20200417/',
               '$var$_Omon_HadGEM3-GC31-MM_dcppA-hindcast_s$sdate$-r1i1p1f2_gn_$chunk$.nc')
sdates <- c('2016', '2017', '2018')

# retrieve = T for verification
suppressWarnings(
data_T <- Start(dat = path,
                var = 'tos',
                sdate = sdates,
                chunk = indices(2:4),
                chunk_depends = 'sdate',
                time = 'all',
                i = indices(450:452),
                j = indices(650:651),
                time_across = 'chunk',
                return_vars = list(time = 'sdate'),
                retrieve = T, silent = T) 
)

test_that("1.a. depending dim is values(); depended dim is indices()", {

suppressWarnings(
data <- Start(dat = path,
               var = 'tos',
               sdate = sdates,
               chunk = indices(2:4),
               chunk_depends = 'sdate',
               time = 'all',
               i = indices(450:452),
               j = indices(650:651),
               time_across = 'chunk',
               return_vars = list(time = 'sdate'),
               retrieve = F)
)
fun <- function(x) {
return(x)
}
step <- Step(fun = fun,
             target_dims = 'dat', output_dims = 'dat')
wf <- AddStep(inputs = data, step_fun = step)
suppressWarnings(
res1 <- Compute(workflow = wf, chunks = list(chunk = 2))$output1
)
suppressWarnings(
res2 <- Compute(workflow = wf, chunks = list(sdate = 2))$output1
)
suppressWarnings(
res3 <- Compute(workflow = wf, chunks = list(chunk = 2, sdate = 2))$output1
)

expect_equal(
as.vector(data_T),
as.vector(res1)
)
expect_equal(
res1,
res2
)
expect_equal(
res1,
res3
)

expect_equal(
as.vector(drop(res1)[, , 1, 1, 1]),
c(29.26021, 29.37948, 30.43721, 30.66117, 30.09621, 30.14460, 30.19445, 30.93453, 30.50104),
tolerance = 0.0001
)
expect_equal(
as.vector(drop(res1)[, , 2, 1, 1]),
c(29.73614, 29.38624, 30.58396, 30.66175, 30.09205, 30.11643, 29.82516, 30.57528, 30.12949),
tolerance = 0.0001
)

})

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

test_that("1.b. depending dim is values(); depended dim is list of values", {

chunks <- list('2016' = c("201701-201712","201801-201812","201901-201912"),
               '2017' = c("201801-201812","201901-201912","202001-202012"),
               '2018' = c("201901-201912","202001-202012","202101-202112"))
suppressWarnings(
data <- Start(dat = path,
               var = 'tos',
               sdate = sdates,
               chunk = chunks,
               chunk_depends = 'sdate',
               time = 'all',
               i = indices(450:452),
               j = indices(650:651),
               time_across = 'chunk',
               return_vars = list(time = 'sdate'),
               retrieve = F)
)
fun <- function(x) {
return(x)
}
step <- Step(fun = fun,
             target_dims = 'dat', output_dims = 'dat')
wf <- AddStep(inputs = data, step_fun = step)

suppressWarnings(
res1 <- Compute(workflow = wf, chunks = list(chunk = 2))$output1
)
suppressWarnings(
res2 <- Compute(workflow = wf, chunks = list(sdate = 2))$output1
)
suppressWarnings(
res3 <- Compute(workflow = wf, chunks = list(chunk = 2, sdate = 2))$output1
)

expect_equal(
as.vector(data_T),
as.vector(res1)
)
expect_equal(
res1,
res2
)
expect_equal(
res1,
res3
)

})

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

test_that("2.a. depending dim is indices(); depended dim is indices()", {

suppressWarnings(
data <- Start(dat = path,
               var = 'tos',
               sdate = indices(57:59), # 2016, 2017, 2018
               chunk = indices(2:4),
               chunk_depends = 'sdate',
               time = 'all',
               i = indices(450:452),
               j = indices(650:651),
               time_across = 'chunk',
               return_vars = list(time = 'sdate'),
               retrieve = F)
)
fun <- function(x) {
return(x)
}
step <- Step(fun = fun,
             target_dims = 'dat', output_dims = 'dat')
wf <- AddStep(inputs = data, step_fun = step)

suppressWarnings(
res1 <- Compute(workflow = wf, chunks = list(chunk = 2))$output1
)
suppressWarnings(
res2 <- Compute(workflow = wf, chunks = list(sdate = 2))$output1
)
suppressWarnings(
res3 <- Compute(workflow = wf, chunks = list(chunk = 2, sdate = 2))$output1
)

expect_equal(
as.vector(data_T),
as.vector(res1)
)
expect_equal(
res1,
res2
)
expect_equal(
res1,
res3
)

})

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

test_that("2.b. depending dim is indices(); depended dim is list of values", {

chunks <- list('2016' = c("201701-201712","201801-201812","201901-201912"),
               '2017' = c("201801-201812","201901-201912","202001-202012"),
               '2018' = c("201901-201912","202001-202012","202101-202112"))
expect_error(
suppressWarnings(
Start(dat = path,
               var = 'tos',
               sdate = indices(57:59), # 2016, 2017, 2018
               chunk = chunks,
               chunk_depends = 'sdate',
               time = 'all',
               i = indices(450:452),
               j = indices(650:651),
               time_across = 'chunk',
               return_vars = list(time = 'sdate'),
               retrieve = F)),
"The depended dimension, chunk, is explictly defined by a list of values, while the depending dimension, sdate, is not explictly defined. Specify sdate by characters."
)

})
