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

# cube0
cube0 <- array(1:5, dim = c(sdate = 5, lon = 4, lat = 4, ftime = 1))
class(cube0) <- 's2dv_cube'

# cube1
cube1 <- NULL
cube1$data <- array(1:5, dim = c(sdate = 5, lon = 4, lat = 4, ftime = 1))
coords2 <- list(sdate = c('20000101', '20010102', '20020103', '20030104', '20040105'), 
                var = 'tas',
                lon = 1.:4., 
                lat = 1.:4.)
cube1$coords <- coords2
dates2 <- c('20000101', '20010102', '20020103', '20030104', '20040105')
dates2 <- as.Date(dates2, format = "%Y%m%d", tz = "UTC")
dim(dates2) <- c(sdate = 5, ftime = 1)
cube1$attrs$Dates <- dates2
class(cube1) <- 's2dv_cube'

# cube2
cube2 <- cube1
cube2$data <- array(1:5, dim = c(sdate = 5, lon = 4, lat = 4, ftime = 1, 
                                 test = 2, test2 = 3))
dim(cube2$data) <- c(sdate = 5, lon = 4, lat = 4, ftime = 1, member = 1, 
                     ensemble = 1, test = 2, test2 = 3)

# cube3
cube3 <- cube1

# dat0
dates0 <- as.Date('2022-02-01', format = "%Y-%m-%d")
dim(dates0) <- c(sdate = 1)

# dat1
dat1 <- array(1, dim = c(test = 1))

# dat2
dat2 <- array(1:5, dim = c(sdate = 5, lon = 4, lat = 4, ftime = 1))
coords2 <- list(sdate = c('20000101', '20010102', '20020103', '20030104', '20040105'), 
                var = 'tas',
                lon = 1.:4., 
                lat = 1.:4.)
dates2 <- c('20000101', '20010102', '20020103', '20030104', '20040105')
dates2 <- as.Date(dates2, format = "%Y%m%d", tz = "UTC")
dim(dates2) <- c(sdate = 5, ftime = 1)

# dat3 (without sdate dim)
dat3 <- array(1:5, dim = c(lon = 4, lat = 4, ftime = 2))
coords3 <- list(sdate = c('20000101', '20010102'), 
                var = 'tas',
                lon = 1.:4., 
                lat = 1.:4.)
dates3 <- c('20000101', '20010102')
dates3 <- as.Date(dates3, format = "%Y%m%d", tz = "UTC")
dim(dates3) <- c(ftime = 2)

# dat4 (without ftime dim)
dat4 <- array(1:5, dim = c(sdate = 2, lon = 4, lat = 4))
coords4 <- list(sdate = c('20000101', '20010102'), 
                var = 'tas',
                lon = 1.:4., 
                lat = 1.:4.)
dates4 <- c('20000101', '20010102')
dates4 <- as.Date(dates4, format = "%Y%m%d", tz = "UTC")
dim(dates4) <- c(sdate = 2)

# dates5 (Dates with extra dimensions)
dates5 <- c('20000101', '20010102',  '20010102',  '20010102')
dates5 <- as.Date(dates5, format = "%Y%m%d", tz = "UTC")
dim(dates5) <- c(ftime = 2, test = 1, test2 = 2)

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

test_that("1. Input checks: CST_SaveExp", {
  # s2dv_cube
  expect_error(
    CST_SaveExp(data = 1), 
    paste0("Parameter 'data' must be of the class 's2dv_cube'.")
  )
  # structure
  expect_error(
    CST_SaveExp(data = cube0), 
    paste0("Parameter 'data' must have at least 'data' and 'attrs' elements ",
           "within the 's2dv_cube' structure.")
  )
  cube0 <- list(data = cube0, attrs = 1)
  class(cube0) <- 's2dv_cube'
  expect_error(
    CST_SaveExp(data = cube0), 
    paste0("Level 'attrs' must be a list with at least 'Dates' element.")
  )

  # sdate_dim
  suppressWarnings(
    expect_error(
      CST_SaveExp(data = cube1, sdate_dim = 1), 
      paste0("Parameter 'sdate_dim' must be a character string.")
    )
  )
  suppressWarnings(
    expect_error(
      CST_SaveExp(data = cube1, sdate_dim = 'a', ftime_dim = 'ftime'), 
      paste0("Parameter 'sdate_dim' is not found in 'data' dimension.")
    )
  )
  # startdates
  expect_warning(
    CST_SaveExp(data = cube1, ftime_dim = 'ftime', memb_dim = NULL, 
                dat_dim = NULL, var_dim = NULL, startdates = 1), 
    paste0("Parameter 'startdates' doesn't have the same length ",
           "as dimension 'sdate', it will not be used.")
  )
  expect_warning(
    CST_SaveExp(data = cube1, ftime_dim = 'ftime', memb_dim = NULL, 
                dat_dim = NULL, var_dim = NULL, startdates = '20100101'), 
    paste0("Parameter 'startdates' doesn't have the same length ",
           "as dimension '", 'sdate',"', it will not be used.")
  )
  # memb_dim
  suppressWarnings(
    expect_error(
      CST_SaveExp(data = cube1, memb_dim = 1, ftime_dim = 'ftime'), 
      paste0("Parameter 'memb_dim' must be a character string.")
    )
  )
  suppressWarnings(
    expect_error(
      CST_SaveExp(data = cube1, memb_dim = 'member', ftime_dim = 'ftime'), 
      paste0("Parameter 'memb_dim' is not found in 'data' dimension. Set it ", 
             "as NULL if there is no member dimension.")
    )
  )
  # metadata
  cube1$attrs$Variable$metadata <- 'metadata'
  expect_error(
    CST_SaveExp(data = cube1, ftime_dim = 'ftime', memb_dim = NULL, 
                dat_dim = NULL, var_dim = NULL), 
    paste0("Element metadata from Variable element in attrs must be a list.")
  )
})

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

test_that("1. Input checks", {
  # data
  expect_error(
    SaveExp(data = NULL),
    "Parameter 'data' cannot be NULL."
  )
  expect_error(
    SaveExp(data = 1:10),
    "Parameter 'data' must be an array with named dimensions."
  )
  # destination
  expect_error(
    SaveExp(data = array(1, dim = c(a = 1)), destination = NULL),
    paste0("Parameter 'destination' must be a character string of one element ",
           "indicating the name of the file (including the folder if needed) ",
           "where the data will be saved."), 
    fixed = TRUE
  )
  # Dates
  expect_error(
    SaveExp(data = array(1, dim = c(a = 1)), Dates = 'a', sdate_dim = NULL,
            memb_dim = NULL, ftime_dim = 'a', dat_dim = NULL, var_dim = NULL),
    paste0("Parameter 'Dates' must be of 'POSIXct' or 'Dates' class.")
  )
  expect_error(
    SaveExp(data = array(1, dim = c(time = 1, sdate = 1, member = 1)), 
            dat_dim = NULL, var_dim = NULL, 
            Dates = as.Date('2022-02-01', format = "%Y-%m-%d")),
    paste0("Parameter 'Dates' must have dimension names.")
  )
  # drop_dims
  expect_warning(
    SaveExp(data = dat2, coords = coords2, 
            metadata = list(tas = list(level = '2m')),
            Dates = dates2, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, drop_dims = 1),
    paste0("Parameter 'drop_dims' must be character string containing ", 
           "the data dimension names to be dropped. It will not be used.")
  )
  expect_warning(
    SaveExp(data = dat2, coords = coords2, 
            metadata = list(tas = list(level = '2m')),
            Dates = dates2, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, drop_dims = 'time'),
    paste0("Parameter 'drop_dims' must be character string containing ", 
           "the data dimension names to be dropped. It will not be used.")
  )
  expect_warning(
    SaveExp(data = dat2, coords = coords2, 
            metadata = list(tas = list(level = '2m')),
            Dates = dates2, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, drop_dims = 'sdate'),
    paste0("Parameter 'drop_dims' can only contain dimension names ", 
           "that are of length 1. It will not be used.")
  )
  expect_warning(
    SaveExp(data = dat2, coords = coords2, 
            metadata = list(tas = list(level = '2m')),
            Dates = dates2, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, drop_dims = 'ftime'),
    paste0("Parameter 'drop_dims' contains dimensions used in the ",
            "computation. It will not be used.")
  )
  # varname
  suppressWarnings(
    expect_error(
      SaveExp(data = dat2, coords = coords2, varname = 1, 
                metadata = list(tas = list(level = '2m')),
                Dates = dates2),
      "Parameter 'varname' must be a character."
    )
  )
  # varname, metadata, spatial coords, unknown dim
  expect_error(
    SaveExp(data = dat1, varname = 1, ftime_dim = NULL, sdate_dim = NULL,  
            memb_dim = NULL, dat_dim = NULL, var_dim = NULL),
    paste0("Parameter 'varname' must be a character string with the ",
           "variable names.")
  )
  # ftime_dim
  expect_error(
    SaveExp(data = dat4, coords = coords4, 
            metadata = list(tas = list(level = '2m')),
            Dates = dates4, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL),
    paste0("Parameter 'ftime_dim' is not found in 'data' dimension.")
  )
  # Dates dimension check
  expect_warning(
    SaveExp(data = dat4, coords = coords4, 
            metadata = list(tas = list(level = '2m')),
            Dates = NULL, ftime_dim = NULL, memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL),
    paste0("Dates must be provided if 'data' must be saved in separated files. ",
            "All data will be saved in a single file.")
  )
  # Without ftime and sdate
  expect_error(
    SaveExp(data = dat3, coords = coords3, 
            metadata = list(tas = list(level = '2m')),
            Dates = dates5, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, sdate_dim = NULL),
    paste0("Parameter 'Dates' can have only 'sdate_dim' and 'ftime_dim' ",
           "dimensions of length greater than 1.")
  )
  expect_warning(
    SaveExp(data = dat2, coords = coords2, 
            metadata = list(tas = list(level = '2m')),
            startdates = c(paste(1:11, collapse = '')), 
            Dates = dates2, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, sdate_dim = 'sdate'),
    paste0("Parameter 'startdates' should be a character string containing ", 
           "the start dates in the format 'yyyy-mm-dd', 'yyyymmdd', 'yyyymm', ", 
           "'POSIXct' or 'Dates' class. Files will be named with Dates instead.")
  )
  expect_warning(
    SaveExp(data = dat2, coords = coords2, 
            metadata = list(tas = list(level = '2m')),
            Dates = NULL, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, sdate_dim = 'sdate'),
    paste0("Dates must be provided if 'data' must be saved in separated files. ",
           "All data will be saved in a single file.")
  )
  # (dat3) Without sdate_dim
  expect_warning(
    SaveExp(data = dat3, coords = coords3, 
            metadata = list(tas = list(level = '2m')),
            Dates = NULL, ftime_dim = 'ftime', memb_dim = NULL, 
            dat_dim = NULL, var_dim = NULL, sdate_dim = NULL,
            extra_string = 'nosdate3.nc', single_file = FALSE),
    paste0("Dates must be provided if 'data' must be saved in separated files. ",
           "All data will be saved in a single file.")
  )
})

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