# Don't perform any further tests on CRAN due to running time.
testthat::skip_on_cran()
testthat::skip_on_ci()

# Create data.table.
data <- familiar:::test_create_good_data(
  outcome_type = "binomial",
  to_data_object = FALSE
)

# Create data assignment object.
experiment_data_assignment <- familiar::precompute_data_assignment(
  data = data,
  experimental_design = "bs(fs+mb,3)",
  outcome_type = "binomial",
  outcome_column = "outcome",
  batch_id_column = "batch_id",
  sample_id_column = "sample_id",
  series_id_column = "series_id",
  class_levels = c("red", "green"),
  verbose = FALSE
)

testthat::test_that("Assert that data assignment performs correctly", {
  testthat::expect_false(is.null(experiment_data_assignment@experiment_setup))
  testthat::expect_false(is.null(experiment_data_assignment@iteration_list))
  testthat::expect_true(is.null(experiment_data_assignment@feature_info))
  testthat::expect_true(is.null(experiment_data_assignment@vimp_table_list))
})

# Create feature info object.
experiment_feature_info <- familiar::precompute_feature_info(
  data = data,
  experiment_data = experiment_data_assignment,
  outcome_type = "binomial",
  outcome_column = "outcome",
  batch_id_column = "batch_id",
  sample_id_column = "sample_id",
  series_id_column = "series_id",
  class_levels = c("red", "green"),
  verbose = FALSE
)

testthat::test_that("Assert that feature info computation performs correctly", {
  # Check that 4 subsets are present, namely generic + complete
  testthat::expect_equal(length(experiment_feature_info@feature_info), 4L)
  
  # Check that there are 6 features.
  testthat::expect_equal(length(experiment_feature_info@feature_info$generic), 6L)

  for (feature_info_set in names(experiment_feature_info@feature_info)) {
    for (feature_info in experiment_feature_info@feature_info[[feature_info_set]]) {
      # Assert that feature info has the correct class.
      testthat::expect_s4_class(feature_info, "featureInfo")

      # Assert that the feature information is complete.
      testthat::expect_equal(
        familiar:::feature_info_complete(feature_info), 
        feature_info_set != "generic"
      )
    }
  }

  # Test contents.
  testthat::expect_true(is.null(experiment_feature_info@vimp_table_list))
  testthat::expect_equal(
    experiment_data_assignment@experiment_setup,
    experiment_feature_info@experiment_setup,
    ignore_attr = TRUE
  )
  testthat::expect_equal(
    experiment_data_assignment@iteration_list,
    experiment_feature_info@iteration_list,
    ignore_attr = TRUE
  )
  testthat::expect_equal(
    experiment_data_assignment@project_id,
    experiment_feature_info@project_id
  )
})

# Create variable importance
experiment_vimp <- familiar::precompute_vimp(
  data = data,
  experiment_data = experiment_feature_info,
  vimp_method = "univariate_regression",
  outcome_type = "binomial",
  outcome_column = "outcome",
  batch_id_column = "batch_id",
  sample_id_column = "sample_id",
  series_id_column = "series_id",
  class_levels = c("red", "green"),
  verbose = FALSE
)

testthat::test_that("Assert that variable importance computation performs correctly", {
  # Assert that variable importance data are correct.
  testthat::expect_length(experiment_vimp@vimp_table_list, 3L)
  for (vimp_table in experiment_vimp@vimp_table_list) {
    testthat::expect_s4_class(vimp_table, "vimpTable")
  }

  # Test contents.
  testthat::expect_equal(
    experiment_data_assignment@experiment_setup,
    experiment_vimp@experiment_setup,
    ignore_attr = TRUE
  )
  testthat::expect_equal(
    experiment_data_assignment@iteration_list,
    experiment_vimp@iteration_list,
    ignore_attr = TRUE
  )
  testthat::expect_equal(
    experiment_feature_info@feature_info,
    experiment_vimp@feature_info,
    ignore_attr = TRUE
  )
  testthat::expect_equal(
    experiment_data_assignment@project_id,
    experiment_vimp@project_id
  )

  # Test that get_vimp_table produces three tables.
  vimp_table <- familiar::get_vimp_table(experiment_vimp@vimp_table_list)
  testthat::expect_length(vimp_table, 3L)

  # Test that aggregate_vimp_table produces one table.
  vimp_table <- familiar::aggregate_vimp_table(
    experiment_vimp@vimp_table_list, 
    aggregation_method = "borda"
  )
  testthat::expect_s4_class(vimp_table, "vimpTable")
  
  vimp_table <- familiar::get_vimp_table(vimp_table)
  testthat::expect_s3_class(vimp_table, "data.table")
})

# Add additional variable importance methods.
experiment_vimp_3 <- familiar::precompute_vimp(
  data = data,
  experiment_data = experiment_vimp,
  vimp_method = c("univariate_regression", "mim", "mrmr"),
  outcome_type = "binomial",
  outcome_column = "outcome",
  batch_id_column = "batch_id",
  sample_id_column = "sample_id",
  series_id_column = "series_id",
  class_levels = c("red", "green"),
  verbose = FALSE
)

testthat::test_that("Addition variable importance computation performs correctly", {
  # Assert that the vimp tables for the univariate_regression method are not
  # altered.
  for (ii in 1L:3L) {
    testthat::expect_equal(
      experiment_vimp_3@vimp_table_list[[ii]],
      experiment_vimp@vimp_table_list[[ii]],
      ignore_attr = TRUE
    )
  }

  # Test that 9 variable importance tables were created.
  testthat::expect_length(
    familiar::get_vimp_table(experiment_vimp_3@vimp_table_list), 9L
  )

  # Test that 3 aggregated variable importance tables are created.
  testthat::expect_length(
    familiar::get_vimp_table(
      familiar::aggregate_vimp_table(experiment_vimp_3@vimp_table_list, "borda")
    ),
    3L
  )

  testthat::expect_equal(
    experiment_vimp@project_id,
    experiment_vimp_3@project_id)
})
