##############################################
 # case 1
 set.seed(1)
 exp1 <- array(rnorm(15), dim = c(sdate = 3, dataset = 5))
 set.seed(2)
 obs1 <- array(rnorm(6), dim = c(sdate = 3, dataset = 2))
 set.seed(3)
 ref1_1 <- array(rnorm(15), dim = c(sdate = 3, dataset = 5))
 ref1_2 <- exp1[, 3]
 dim(ref1_2) <- c(sdate = 3)

 # case 2
 set.seed(3)
 exp2 <- array(rnorm(30), dim = c(dataset = 3, sdate = 5, member = 3))
 set.seed(4)
 obs2 <- array(rnorm(20), dim = c(dataset = 2, sdate = 5, member = 2))
 set.seed(5)
 ref2 <- array(rnorm(15), dim = c(sdate = 5, member = 3))

 # case 3: vector
 set.seed(5)
 exp3 <- rnorm(10)
 set.seed(6)
 obs3 <- rnorm(10)


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

test_that("1. Input checks", {
  ## exp and obs (1)
  expect_error(
  RMSSS(c(), c()),
  "Parameter 'exp' and 'obs' cannot be NULL."
  )
  expect_error(
  RMSSS('exp', 'obs'),
  "Parameter 'exp' and 'obs' must be a numeric array."
  )
  expect_error(
  RMSSS(c(1:10), c(2:4)),
  paste0("Parameter 'exp' and 'obs' must be array with as least two dimensions ",
         "time_dim and dat_dim, or vector of same length.")
  )
  expect_error(
  RMSSS(array(1:10, dim = c(2, 5)), array(1:10, dim = c(2, 5))),
  "Parameter 'exp' and 'obs' must have dimension names."
  )
  expect_error(
  RMSSS(array(1:20, dim = c(dat = 2, sdate = 5, member = 2)),
        array(1:10, dim = c(dat = 2, sdate = 5, time = 1))),
  "Parameter 'exp' and 'obs' must have the same dimension names."
  )
  ## time_dim
  expect_error(
  RMSSS(exp1, obs1, time_dim = 1),
  "Parameter 'time_dim' must be a character string."
  )
  expect_error(
  RMSSS(exp1, obs1, time_dim = 'a'),
  "Parameter 'time_dim' is not found in 'exp' or 'obs' dimension."
  )
  ## dat_dim
  expect_error(
  RMSSS(exp1, obs1, dat_dim = NA),
  "Parameter 'dat_dim' must be a character string."
  )
  expect_error(
  RMSSS(exp1, obs1, dat_dim = 'memb'),
  paste0("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.",
           " Set it as NULL if there is no dataset dimension.")
  )
  ## pval
  expect_error(
  RMSSS(exp1, obs1, pval = c(T, T)),
  "Parameter 'pval' must be one logical value."
  )
  ## sign
  expect_error(
  RMSSS(exp1, obs1, sign = 0.05),
  "Parameter 'sign' must be one logical value."
  )
  ## alpha
  expect_error(
  RMSSS(exp1, obs1, alpha = T),
  "Parameter 'alpha' must be one numeric value."
  )
  ## ncores
  expect_error(
  RMSSS(exp1, obs1, ncores = 1.4),
  "Parameter 'ncores' must be a positive integer."
  )
  ## exp and obs (2)
  expect_error(
  RMSSS(exp = array(1:10, dim = c(dataset = 1, member = 5, sdate = 1)),
        obs = array(1:4, dim = c(dataset = 2, member = 2, sdate = 2))),
  "Parameter 'exp' and 'obs' must have same length of all dimensions except 'dat_dim' and 'memb_dim'."
  )
  expect_error(
  RMSSS(exp = array(1:10, dim = c(sdate = 1, dataset = 5, a = 1)),
        obs = array(1:4, dim = c(a = 1, sdate = 1, dataset = 2)), dat_dim = "dataset"),
  "The length of time_dim must be more than 2 to compute RMSSS."
  )
})

##############################################
test_that("2. Output checks: case 1", {

  res1_1 <- RMSSS(exp1, obs1, dat_dim = 'dataset')
  expect_equal(
    dim(res1_1$rmsss),
    c(nexp = 5, nobs = 2)
  )
  expect_equal(
    dim(res1_1$p.val),
    c(nexp = 5, nobs = 2)
  )
  expect_equal(
  c(res1_1$rmsss)[3:8],
  c(0.01693900, -0.02730428, -0.34167869, 0.01588531, -1.55611403, -0.63596896),
    tolerance = 0.00001
  )
  expect_equal(
  as.vector(res1_1$p.val)[3:7],
  c(0.4914588, 0.5134658, 0.6428701, 0.4919943, 0.8672634),
  tolerance = 0.001
  )

  exp1_2 <- exp1; exp1_2[2:4] <- NA
  obs1_2 <- obs1; obs1_2[1:2] <- NA
  res1_2 <- RMSSS(exp1_2, obs1_2, dat_dim = 'dataset', pval = T, sign = T)

  expect_equal(
  names(res1_2),
  c("rmsss", "p.val", "sign")
  )
  expect_equal(
  c(res1_2$rmsss),
  c(rep(NA, 7), -0.6359690, -0.5877153, -1.1108657),
  tolerance = 0.0001
  )
  expect_equal(
  c(res1_2$p.val),
  c(rep(NA, 7), 0.7279944, 0.7159769, 0.8167073),
  tolerance = 0.0001
  )
  expect_equal(
  c(res1_2$sign),
  c(rep(NA, 7), rep(FALSE, 3))
  )

  #ref
  res1_3 <- RMSSS(exp1, obs1, ref = ref1_1, dat_dim = 'dataset')
  expect_equal(
  dim(res1_3$rmsss),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  dim(res1_3$p.val),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  as.vector(res1_3$rmsss[2, ]),
  c(-1.197432, -8.879809),
  tolerance = 0.0001
  )
  expect_equal(
  as.vector(res1_3$p.val[2, ]),
  c(0.8284354, 0.9898591),
  tolerance = 0.0001
  )
  res1_4 <- RMSSS(exp1, obs1, ref = ref1_2, dat_dim = 'dataset', sign = T, alpha = 0.3)
  expect_equal(
  dim(res1_4$rmsss),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  dim(res1_4$sign),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  as.vector(res1_4$rmsss[2, ]),
  c(-0.9249772, -0.5624465),
  tolerance = 0.0001
  )
  expect_equal(
  as.vector(res1_4$p[2, ]),
  c(0.7874844, 0.7094070),
  tolerance = 0.0001
  )
  expect_equal(
  as.vector(res1_4$sign),
  c(rep(F, 5), T, rep(F, 4))
  )

  # Random Walk
  suppressWarnings({
  res1_5 <- RMSSS(exp1, obs1, ref = ref1_1, dat_dim = 'dataset', sig_method = "Random Walk", pval = F, sign = T, sig_method.type = 'two.sided.approx')
  })
  expect_equal( 
  as.vector(res1_5$sign),
  rep(F, 10)
  )
  suppressWarnings({
  res1_6 <- RMSSS(exp1, obs1, ref = NULL, dat_dim = 'dataset', sig_method = "Random Walk", pval = F, sign = T, sig_method.type = 'two.sided.approx')
  })
  expect_equal(
  as.vector(res1_6$sign),
  rep(F, 10)
  )

  suppressWarnings({
  res1_7 <- RMSSS(exp1, obs1, ref = NULL, dat_dim = 'dataset', sig_method = "Random Walk", pval = T, sign = T, sig_method.type = 'two.sided', alpha = 0.4)
  })
  expect_equal(
  names(res1_7),
  c('rmsss', 'p.val', 'sign')
  )
  expect_equal(
  res1_7$rmsss,
  res1_6$rmsss
  )
  expect_equal(
  c(res1_7$p[, 2]),
  c(1, 0.25, 0.25, 1, 1),
  tolerance = 0.0001
  )
  expect_equal(
  c(res1_7$sign[, 2]),
  c(F, T, T, F, F)
  )
})


##############################################
test_that("3. Output checks: case 2", {
  res1 <- RMSSS(exp2, obs2, ref2, dat_dim = "dataset", memb_dim = 'member', sign = T)
  expect_equal(
  dim(res1$rmsss),
  c(nexp = 3, nobs = 2) 
  )
  expect_equal(
  dim(res1$sign),
  c(nexp = 3, nobs = 2)                            
  )
  expect_equal(    
  dim(res1$p),
  c(nexp = 3, nobs = 2)                            
  )
  expect_equal(
  c(res1$rmsss),
  c(-0.08699446, 0.30703938, -0.28888291, -0.04284967, 0.39097270, -0.39792484),
  tolerance = 0.0001
  )
  expect_equal(
  c(res1$p),
  c(0.5622736, 0.2474466, 0.6825138, 0.5314309, 0.1799964, 0.7338230),
  tolerance = 0.0001
  )


  res2 <- RMSSS(apply(exp2, 1:2, mean), apply(obs2, 1:2, mean), array(apply(ref2, 1, mean), dim = c(sdate = 5)),dat_dim = "dataset", sign = T)
  expect_equal(    
  res1, res2
  )

})

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

test_that("4. Output checks: case 3", {

  expect_equal(
    dim(RMSSS(exp3, obs3)$rmsss),
    NULL
  )
  expect_equal(
  as.vector(RMSSS(exp3, obs3)$rmsss),
  -0.6289915,
  tolerance = 0.00001
  )

})
