context("Generic tests")
test_that("Sanity checks and simple use cases", {
  # Generate simple synthetic data
  # 4x5 in space, 2 members, 3 sdates, 6 ftime
  r <- exp(rnorm(1 * 2 * 3 * 6 * 5 * 4))
  dim(r) <- c(dataset = 1, member = 2, sdate = 3, ftime = 6, lat = 5, lon = 4)
  lon <- seq(0, 6, 2)
  lat <- seq(10, 18, 2)
  exp <- list(data = r, lat = lat, lon = lon)
  attr(exp, 'class') <- 's2dv_cube'

  expect_warning(
    res <- CST_RainFARM(exp, nf=8),
    "input data are expected to be on a square grid with an even number of pixels per side."
  )
  # Using a correct square dataset
  r <- exp(rnorm(1 * 2 * 3 * 6 * 4 * 4))
  dim(r) <- c(dataset = 1, member = 2, sdate = 3, ftime = 6, lat = 4, lon = 4)
  lat <- seq(10, 16, 2)
  exp <- list(data = r, lat = lat, lon = lon)
  attr(exp, 'class') <- 's2dv_cube'

  expect_warning(
    res <- CST_RainFARM(exp, nf=8),
    "Selected time dim: ftime"
  )
  expect_error(
    res <- CST_RainFARM(exp, nf=8, weights=array(0,dim=c(2,2))),
    "The dimensions of the weights matrix"
  )
  
  dimexp=dim(exp$data)

  res <- CST_RainFARM(exp, nf=8, time_dim=c("ftime", "sdate"), slope=1.7, nens=2)
  expect_equal(dim(res$data), c(dimexp["dataset"], dimexp["member"], 
                                realization = 2, dimexp["sdate"],
                                dimexp["ftime"], dimexp["lat"] * 8,
                                dimexp["lon"] * 8))

  expect_equivalent(length(res$lon), dimexp["lon"] * 8) 
  expect_equivalent(length(res$lat), dimexp["lat"] * 8) 

  res <- CST_RainFARM(exp, nf=8, time_dim=c("ftime", "sdate"),
                      nens=2, drop_realization_dim=TRUE)
  expect_equal(dim(res$data), c(dimexp["dataset"], dimexp["member"] * 2,
                                dimexp["sdate"],
                                dimexp["ftime"], dimexp["lat"] * 8,
                                dimexp["lon"] * 8))

  res <- CST_RainFARM(exp, nf=8, time_dim=c("ftime", "sdate"), slope=1.7,
                      nens=2, nproc=2, fsmooth=FALSE)
  expect_equal(dim(res$data), c(dimexp["dataset"], dimexp["member"], 
                                realization = 2, dimexp["sdate"],
                                dimexp["ftime"], dimexp["lat"] * 8,
                                dimexp["lon"] * 8))

  # Use rainfarmr package functions to test for consistency

  # Aggregated downscaled data should be the same as original

  expect_equivalent(agg(res$data[1,1,1,1,1,,], 4), exp$data[1,1,1,1,,])

  res <- CST_RainFARM(exp, nf=8, time_dim=c("ftime", "sdate"),
                      nens=2, nproc=2, fglob=TRUE)

  expect_equal(mean(agg(res$data[1,1,1,1,1,,], 4)),
                   mean(exp$data[1,1,1,1,,]))

  dim(r) <- c(dataset = 1, member = 2, sdate = 3, ftime = 6, lat = 5, lon = 4)

  # Create a more realistic perfect-model precipitation
  z <- 1 : (32 * 32)
  dim(z) <- c(32, 32)
  x=rep(-15:16,32); dim(x) <- c(32, 32);  x=x+4 ; y<-t(x);
  z<-sqrt(x^2+y^2); z=(z<=12)*(z>=8)*0.8+0.6
  
  exppf <- exp 
  nens = 10
  exppf$data <- array(1. , c(1, nens, 3, 6, 4, 4))
  dim(exppf$data) <- c(dataset = 1, member = nens, sdate = 3,
                       ftime = 6, lat = 4, lon = 4)
  rpf <- array(1. , c(1, nens, 3, 6, 32, 32))
  for (i in 1:nens) {
    for (j in 1:3) {
      for (k in 1:6) {
        f = initmetagauss(1.7, 32)
        r = exp(metagauss(f)) * z
        rpf[1, i, j, k, , ] <- r
        exppf$data[1, i, j, k, , ] <- agg(r, 4)
      }
    }
  }
  rpfm=agg(apply(rpf, c(5, 6), mean),32)

  # Use climatological mean of PF precipitation to generate sythetic weights
  w <- rfweights(rpfm, res$lon, res$lat, exp$lon, exp$lat, 8, fsmooth=FALSE )

  res <- CST_RainFARM(exppf, nf=8, time_dim=c("ftime", "sdate", "member"),
                      nens=2, nproc=2, fsmooth=FALSE)
  resw <- CST_RainFARM(exppf, nf=8, time_dim=c("ftime", "sdate", "member"),
                      nens=2, nproc=2, fsmooth=FALSE, weights=w)
  resm <- agg(apply(res$data, c(6,7), mean),32)
  reswm <- agg(apply(resw$data, c(6,7), mean),32)
  
  # Things should work much  better with weights compared to no weights
  expect_lt(mean((reswm-rpfm)^2), mean((resm-rpfm)^2)*0.5)

  # Test if downscaled data have similar slope to input data
  # Synthetic fine-scale data with slope 1.7 
  f = initmetagauss(1.7, 256)
  r = exp(metagauss(f))
  ra <- agg(r, 8)
  dim(ra) <- c(dataset = 1, member = 1, sdate = 1, ftime = 1, lat = 8, lon = 8)
  expcoarse <- exp
  expcoarse$data <- ra
  dim(r) <- c(dataset = 1, member = 1, sdate = 1, ftime = 1, lat = 256, lon = 256)
  expfine <- exp
  expfine$data <- r
  res <- CST_RainFARM(expcoarse, nf=32, time_dim=c("ftime", "sdate"),
                      slope=1.7, fsmooth=FALSE, drop_realization_dim=TRUE)
  sres= CST_RFSlope(res, time_dim = c("ftime", "sdate"))
  sexp= CST_RFSlope(expfine, time_dim = c("ftime", "sdate"))
  expect_equal(sres, sexp, tolerance=0.25)
})  
