##############################################
 # 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(
  MSSS(c(), c()),
  "Parameter 'exp' and 'obs' cannot be NULL."
  )
  expect_error(
  MSSS('exp', 'obs'),
  "Parameter 'exp' and 'obs' must be a numeric array."
  )
  expect_error(
  MSSS(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(
  MSSS(array(1:10, dim = c(2, 5)), array(1:10, dim = c(2, 5))),
  "Parameter 'exp' and 'obs' must have dimension names."
  )
  expect_error(
  MSSS(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(
  MSSS(exp1, obs1, time_dim = 1),
  "Parameter 'time_dim' must be a character string."
  )
  expect_error(
  MSSS(exp1, obs1, time_dim = 'a'),
  "Parameter 'time_dim' is not found in 'exp' or 'obs' dimension."
  )
  ## dat_dim
  expect_error(
  MSSS(exp1, obs1, dat_dim = NA),
  "Parameter 'dat_dim' must be a character string."
  )
  expect_error(
  MSSS(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(
  MSSS(exp1, obs1, pval = c(T, T)),
  "Parameter 'pval' must be one logical value."
  )
  ## sign
  expect_error(
  MSSS(exp1, obs1, sign = 0.05),
  "Parameter 'sign' must be one logical value."
  )
  ## alpha
  expect_error(
  MSSS(exp1, obs1, alpha = T),
  "Parameter 'alpha' must be one numeric value."
  )
  ## ncores
  expect_error(
  MSSS(exp1, obs1, ncores = 1.4),
  "Parameter 'ncores' must be a positive integer."
  )
  ## exp and obs (2)
  expect_error(
  MSSS(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(
  MSSS(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 MSSS."
  )
})

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

  res1_1 <- MSSS(exp1, obs1, dat_dim = 'dataset')
  expect_equal(
    dim(res1_1$msss),
    c(nexp = 5, nobs = 2)
  )
  expect_equal(
    dim(res1_1$p.val),
    c(nexp = 5, nobs = 2)
  )
  expect_equal(
  c(res1_1$msss)[3:8],
  c(0.03359106, -0.05535409, -0.80010171, 0.03151828, -5.53371892, -1.67639444),
    tolerance = 0.00001
  )
  expect_equal(
  as.vector(res1_1$p.val)[3:7],
  c(0.4829225, 0.5269121, 0.7641713, 0.4839926, 0.9771112),
  tolerance = 0.001
  )

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

  expect_equal(
  names(res1_2),
  c("msss", "p.val", "sign")
  )
  expect_equal(
  c(res1_2$msss),
  c(rep(NA, 7), -1.676394, -1.520840, -3.455754),
  tolerance = 0.0001
  )
  expect_equal(
  c(res1_2$p.val),
  c(rep(NA, 7), 0.8774973, 0.8640313, 0.9520470),
  tolerance = 0.0001
  )
  expect_equal(
  c(res1_2$sign),
  c(rep(NA, 7), rep(FALSE, 3))
  )

  #ref
  res1_3 <- MSSS(exp1, obs1, ref = ref1_1, dat_dim = 'dataset')
  expect_equal(
  dim(res1_3$msss),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  dim(res1_3$p.val),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  as.vector(res1_3$msss[2, ]),
  c(-3.828708, -96.610622),
  tolerance = 0.0001
  )
  expect_equal(
  as.vector(res1_3$p.val[2, ]),
  c(0.9588755, 0.9998951),
  tolerance = 0.0001
  )
  res1_4 <- MSSS(exp1, obs1, ref = ref1_2, dat_dim = 'dataset', sign = T, alpha = 0.3)
  expect_equal(
  dim(res1_4$msss),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  dim(res1_4$sign),
  c(nexp = 5, nobs = 2)
  )
  expect_equal(
  as.vector(res1_4$msss[2, ]),
  c(-2.705537, -1.441239),
  tolerance = 0.0001
  )
  expect_equal(
  as.vector(res1_4$p[2, ]),
  c(0.9321160, 0.8563146),
  tolerance = 0.0001
  )
  expect_equal(
  as.vector(res1_4$sign),
  c(rep(F, 5), T, rep(F, 4))
  )

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

})


##############################################
test_that("3. Output checks: case 2", {
  res1 <- MSSS(exp2, obs2, ref2, dat_dim = "dataset", memb_dim = 'member', sign = T)
  expect_equal(
  dim(res1$msss),
  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$msss),
  c(-0.18155696, 0.51980557, -0.66121915, -0.08753543, 0.62908575, -0.95419385),
  tolerance = 0.0001
  )
  expect_equal(
  c(res1$p),
  c(0.62284746, 0.09217502, 0.82539496, 0.56264155, 0.04034091, 0.88868245),
  tolerance = 0.0001
  )

  res2 <- MSSS(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(MSSS(exp3, obs3)$msss),
  NULL
  )
  expect_equal(
  as.vector(MSSS(exp3, obs3)$msss),
  -1.653613,
  tolerance = 0.00001
  )

})
