library(groupdata2)
context("find_missing_starts()")

test_that("find_missing_starts() find the right missing starts", {
  xpectr::set_test_seed(1)

  v <- c("a", "a", "b", "c", "c", "d", "d")
  df <- data.frame(
    v = v,
    v2 = c(1, 1, 1, 2, 2, 2, 3),
    v3 = factor(c(1, 1, 1, 2, 2, 2, 3)),
    stringsAsFactors = FALSE
  )

  check_find_missing_starts_df <- function(n, starts_col, return_skip_numbers = FALSE) {
    find_missing_starts(df,
      n = n, starts_col = starts_col,
      return_skip_numbers = return_skip_numbers
    )
  }

  # find_missing_starts(df, n = c("r", "d"), starts_col = "v")

  # v
  expect_equal(check_find_missing_starts_df(n = c("r", "d"), starts_col = "v"), c("r"))
  expect_equal(check_find_missing_starts_df(
    n = c("r", "d"), starts_col = "v",
    return_skip_numbers = TRUE
  ), list(c("r", "1")))
  expect_equal(check_find_missing_starts_df(n = c("b", "r", "o", "d"), starts_col = "v"), c("r", "o"))
  expect_equal(check_find_missing_starts_df(
    n = c("b", "r", "o", "d"), starts_col = "v",
    return_skip_numbers = TRUE
  ), list(c("r", "1"), c("o", "1")))

  # v2
  expect_equal(check_find_missing_starts_df(n = c(1, 3, 5), starts_col = "v2"), c(5))
  expect_equal(check_find_missing_starts_df(
    n = c(1, 3, 5), starts_col = "v2",
    return_skip_numbers = TRUE
  ), list(c(5, 1)))
  expect_equal(check_find_missing_starts_df(n = c(5, 2, 1), starts_col = "v2"), c("5")) # TODO Why character type here?
  expect_equal(check_find_missing_starts_df(
    n = c(5, 3, 1), starts_col = "v2",
    return_skip_numbers = TRUE
  ), list(c("5", "1")))

  # starts column is factor:

  ## Testing 'check_find_missing_starts_df(n = c(1, 5, 3, ...'              ####
  ## Initially generated by xpectr
  xpectr::set_test_seed(42)
  # Testing side effects
  # Assigning side effects
  side_effects_12655 <- xpectr::capture_side_effects(check_find_missing_starts_df(n = c(1, 5, 3, 7), starts_col = "v3"), reset_seed = TRUE)
  expect_equal(
    xpectr::strip(side_effects_12655[['warnings']]),
    xpectr::strip("'data[[starts_col]]' is factor. Converting to character."),
    fixed = TRUE)
  expect_equal(
    xpectr::strip(side_effects_12655[['messages']]),
    xpectr::strip(character(0)),
    fixed = TRUE)
  # Assigning output
  output_12655 <- xpectr::suppress_mw(check_find_missing_starts_df(n = c(1, 5, 3, 7), starts_col = "v3"))
  # Testing class
  expect_equal(
    class(output_12655),
    "numeric",
    fixed = TRUE)
  # Testing type
  expect_type(
    output_12655,
    type = "double")
  # Testing values
  expect_equal(
    output_12655,
    c(5, 7),
    tolerance = 1e-4)
  # Testing names
  expect_equal(
    names(output_12655),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(output_12655),
    2L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(output_12655)),
    2L)
  ## Finished testing 'check_find_missing_starts_df(n = c(1, 5, 3, ...'     ####


  # Example from docs:

  # Create a data frame
  df <- data.frame("a" = factor(c("a", "a", "b", "b", "c", "c")))

  # Create list of starts
  starts <- c("a", "e", "b", "d", "c")

  # Find missing starts with skip_to numbers:

  ## Testing 'find_missing_starts(df, starts, starts_col =...'              ####
  ## Initially generated by xpectr
  xpectr::set_test_seed(42)
  # Testing side effects
  # Assigning side effects
  side_effects_19148 <- xpectr::capture_side_effects(find_missing_starts(df, starts, starts_col = "a"), reset_seed = TRUE)
  expect_equal(
    xpectr::strip(side_effects_19148[['warnings']]),
    xpectr::strip("'data[[starts_col]]' is factor. Converting to character."),
    fixed = TRUE)
  expect_equal(
    xpectr::strip(side_effects_19148[['messages']]),
    xpectr::strip(character(0)),
    fixed = TRUE)
  # Assigning output
  output_19148 <- xpectr::suppress_mw(find_missing_starts(df, starts, starts_col = "a"))
  # Testing class
  expect_equal(
    class(output_19148),
    "list",
    fixed = TRUE)
  # Testing type
  expect_type(
    output_19148,
    type = "list")
  # Testing values
  expect_equal(
    output_19148,
    list(c("e", "1"), c("d", "1")))
  # Testing names
  expect_equal(
    names(output_19148),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(output_19148),
    2L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(output_19148)),
    4L)
  ## Finished testing 'find_missing_starts(df, starts, starts_col =...'     ####

  # Find missing starts without skip_to numbers


  ## Testing 'find_missing_starts(df, starts, starts_col =...'              ####
  ## Initially generated by xpectr
  xpectr::set_test_seed(42)
  # Testing side effects
  # Assigning side effects
  side_effects_19148 <- xpectr::capture_side_effects(find_missing_starts(df, starts, starts_col = "a", return_skip_numbers = FALSE), reset_seed = TRUE)
  expect_equal(
    xpectr::strip(side_effects_19148[['warnings']]),
    xpectr::strip("'data[[starts_col]]' is factor. Converting to character."),
    fixed = TRUE)
  expect_equal(
    xpectr::strip(side_effects_19148[['messages']]),
    xpectr::strip(character(0)),
    fixed = TRUE)
  # Assigning output
  output_19148 <- xpectr::suppress_mw(find_missing_starts(df, starts, starts_col = "a", return_skip_numbers = FALSE))
  # Testing class
  expect_equal(
    class(output_19148),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    output_19148,
    type = "character")
  # Testing values
  expect_equal(
    output_19148,
    c("e", "d"),
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(output_19148),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(output_19148),
    2L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(output_19148)),
    2L)
  ## Finished testing 'find_missing_starts(df, starts, starts_col =...'     ####

  # Warning and errors

  expect_error(
    xpectr::strip_msg(find_missing_starts(c(1, 2, 3, 4), starts_col = "v")),
    xpectr::strip("argument \"n\" is missing, with no default"),
    fixed = TRUE)

  expect_error(
    xpectr::strip_msg(find_missing_starts(c(1, 2, 3, 4), n = c("a"), starts_col = "v")),
    xpectr::strip(paste0("1 assertions failed:\n * when 'starts_col' is specified, 'd",
                         "ata' must be a data frame.")),
    fixed = TRUE)

  expect_error(
    xpectr::strip_msg(find_missing_starts(df, n = c("a"), starts_col = NULL)),
    xpectr::strip(paste0("1 assertions failed:\n * when 'data' is a data frame, 'star",
                         "ts_col' must be specified.")),
    fixed = TRUE)

  if (FALSE){
    # TODO Fix when checkmate is updated
    expect_error(
      xpectr::strip_msg(find_missing_starts(c(1, 2, 3, 4), n = data.frame("a" = c(3, 4, 5)))),
      xpectr::strip(paste0("Assertion failed. One of the following must apply:\n * chec",
                           "kmate::check_numeric(n): Must be of type 'numeric', not 'dat",
                           "a.frame'\n * checkmate::check_character(n): Must be of type ",
                           "'character', not 'data.frame'\n * checkmate::check_list(n): ",
                           "Must be of type 'list', not 'data.frame'")),
      fixed = TRUE)
  }

  expect_error(
    xpectr::strip_msg(find_missing_starts(c(1, 2, 3, 4), n = c(3), return_skip_numbers = 3)),
    xpectr::strip(paste0("1 assertions failed:\n * Variable 'return_skip_numbers': Mu",
                         "st be of type 'logical flag', not 'double'.")),
    fixed = TRUE)

})

test_that("fold() works with group_by()", {
  xpectr::set_test_seed(42)

  v <- c("a", "a", "b", "c", "c", "d", "d")
  df <- data.frame(
    v = v,
    v2 = c(1, 1, 1, 2, 2, 2, 3),
    v3 = factor(c(1, 1, 1, 2, 2, 2, 3)),
    v4 = paste0("g_",c(1, 1, 1, 2, 2, 2, 3)),
    stringsAsFactors = FALSE
  )


  ## Testing 'xpectr::suppress_mw( df %>% dplyr::group_by(...'              ####
  ## Initially generated by xpectr
  xpectr::set_test_seed(42)
  # Assigning output
  output_19148 <- xpectr::suppress_mw(
      df %>%
        dplyr::group_by(v4) %>%
        find_missing_starts(
          n = "e",
          starts_col = "v",
          return_skip_numbers = TRUE
        )
    )
  # Testing class
  expect_equal(
    class(output_19148),
    "list",
    fixed = TRUE)
  # Testing type
  expect_type(
    output_19148,
    type = "list")
  # Testing values
  expect_equal(
    output_19148[["1"]],
    list(c("e", "1")))
  expect_equal(
    output_19148[["2"]],
    list(c("e", "1")))
  expect_equal(
    output_19148[["3"]],
    list(c("e", "1")))
  # Testing names
  expect_equal(
    names(output_19148),
    c("1", "2", "3"),
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(output_19148),
    3L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(output_19148)),
    3L)
  # Testing element classes
  expect_equal(
    xpectr::element_classes(output_19148),
    c("list", "list", "list"),
    fixed = TRUE)
  # Testing element types
  expect_equal(
    xpectr::element_types(output_19148),
    c("list", "list", "list"),
    fixed = TRUE)
  ## Finished testing 'xpectr::suppress_mw( df %>% dplyr::group_by(...'     ####


})
