# If dataset are more than 1 (e.g., exp and obs), ByChunks() checks if 
# they have consistent dimensions in favor of Apply() computation. However,
# only margin dimensions need to be identical. Target dimensions can have
# different lengths.

test_that("ex2_11", {
path.exp <- '/esarchive/exp/ecmwf/system5c3s/monthly_mean/$var$_f6h/$var$_$sdate$.nc'
path.exp <- paste0('/esarchive/scratch/aho/startR_unittest_files/', path.exp)
path.obs <- '/esarchive/recon/ecmwf/era5/monthly_mean/$var$_f1h-r1440x721cds/$var$_$date$.nc'
path.obs <- paste0('/esarchive/scratch/aho/startR_unittest_files/', path.obs)

var <- 'tos'
y1 <- 1981
y2 <- 1983

lons.min <- 220
lons.max <- 240
lats.min <- -5
lats.max <- 5

sdate <- paste0(y1:y2, '1201')

suppressWarnings(
exp <- Start(data = path.exp,
             var = var,
             member = indices(1:2),
             sdate = sdate,
             time = 1:3,
             latitude = values(list(lats.min, lats.max)),
             latitude_reorder = Sort(decreasing = TRUE),
             longitude = values(list(lons.min, lons.max)),
             synonims = list(longitude = c('lon', 'longitude'),
                             latitude = c('lat', 'latitude'),
                             member = c('member', 'ensemble')),
             return_vars = list(longitude = NULL,
                                latitude = NULL,
                                time = 'sdate'),
             retrieve = FALSE)
)
lons.exp <- attr(exp, 'Variables')$common$longitude
lats.exp <- attr(exp, 'Variables')$common$latitude
dates.exp <- attr(exp, 'Variables')$common$time

# Manually create date/ime
dates.obs <- c(paste0(y1:y2, '1201'),
               paste0((y1 + 1):(y2 + 1), '01', '01'),
               paste0((y1 + 1):(y2 + 1), '02', '01'))
time.obs <- as.POSIXct(dates.obs, "%Y%m%d",
                       origin = "1981-12", tz = 'UTC')
dim(time.obs) <- c(dim(dates.exp)['sdate'], dim(dates.exp)['time'])

suppressWarnings(
obs <- Start(data = path.obs,
             var = var,
             date = unique(format(time.obs, '%Y%m')),
             time = values(time.obs),
             latitude = values(list(lats.min, lats.max)),
             latitude_reorder = Sort(decreasing = TRUE),
             longitude = values(list(lons.min, lons.max)),
             time_across = 'date',
             merge_across_dims = TRUE,
             split_multiselected_dims = TRUE,
             synonims = list(longitude = c('lon', 'longitude'),
                             latitude = c('lat', 'latitude')),
             return_vars = list(longitude = NULL,
                                latitude = NULL,
                                time = 'date'),
             retrieve = FALSE)
)

fun <- function(exp, obs) {
# exp: [member = 2, latitude = 11, longitude = 21]
# obs: [latitude = 41, longitude = 81]
  return(list(exp = exp, obs = obs))
}

step <- Step(fun,
             target_dims = list(exp = c('member', 'latitude', 'longitude'),
                                obs = c('latitude', 'longitude')),
             output_dims = list(exp = c('member', 'latitude', 'longitude'),
                                obs = c('latitude', 'longitude')))

workflow <- AddStep(list(exp = exp, obs = obs), step)

suppressWarnings(
res <- Compute(workflow$exp, chunks = list(sdate = 2))
)

expect_equal(
attr(exp, 'Dimensions'),
c(data = 1, var = 1, member = 2, sdate = 3, time = 3, latitude = 11, longitude = 21)
)
expect_equal(
attr(obs, 'Dimensions'),
c(data = 1, var = 1, sdate = 3, time = 3, latitude = 41, longitude = 81)
)
expect_equal(
names(res),
c('exp', 'obs')
)
expect_equal(
dim(res$exp),
c(member = 2, latitude = 11, longitude = 21, data = 1, var = 1, sdate = 3, time = 3)
)
expect_equal(
dim(res$obs),
c(latitude = 41, longitude = 81, data = 1, var = 1, sdate = 3, time = 3)
)
expect_equal(
mean(res$exp),
299.5028,
tolerance = 0.0001
)
expect_equal(
mean(res$obs),
299.8896,
tolerance = 0.0001
)
expect_equal(
res$exp[1, 1:5, 2, 1, 1, 2, 2],
c(302.2021, 302.3682, 302.4512, 302.4404, 302.4922),
tolerance = 0.0001
)
expect_equal(
res$exp[2, 1:5, 2, 1, 1, 2, 3],
c(301.4209, 301.4795, 301.4004, 301.3633, 301.5791),
tolerance = 0.0001
)
expect_equal(
res$obs[1:5, 2, 1, 1, 2, 2],
c(301.5615, 301.5351, 301.6196, 301.7573, 301.8423),
tolerance = 0.0001
)
expect_equal(
res$obs[5, 1:5, 1, 1, 3, 2],
c(299.6043, 299.6480, 299.6803, 299.6851, 299.6761),
tolerance = 0.0001
)

})
