library(cvms)
context("simplify_formula()")

test_that("formulas are properly simplified with simplify_formula()", {

  df <- data.frame("a" = c(1,2,3,4), "b" = c(2,3,4,5), "c" = c(3,4,5,6))

  f1 <- "y ~ x*z + log(a) + (1|b)"

  expect_equal(simplify_formula(f1), as.formula("y ~ x + z + a + b"))
  expect_equal(simplify_formula(as.formula(f1)), as.formula("y ~ x + z + a + b"))

  f2 <- "y ~ ."

  expect_equal(simplify_formula(f2, data = df), as.formula("y ~ a + b + c"))
  expect_equal(simplify_formula(as.formula(f2), data = df), as.formula("y ~ a + b + c"))

  df[["y"]] <- c(0,1,0,1)

  expect_equal(simplify_formula(f2, data = df), as.formula("y ~ a + b + c"))
  expect_equal(simplify_formula(as.formula(f2), data = df), as.formula("y ~ a + b + c"))

  f3 <- "y ~ x*z + t:p + exp(a) + (1+d*e|b)"

  expect_equal(simplify_formula(f3, data = df), as.formula("y ~ x + z + t + p + a + d + e + b"))
  expect_equal(simplify_formula(as.formula(f3), data = df), as.formula("y ~ x + z + t + p + a + d + e + b"))

})

test_that("correct outputs with simplify_formula()", {

  df <- data.frame("a" = c(1,2,3,4), "b" = c(2,3,4,5), "c" = c(3,4,5,6))

  ## Code for generating below tests ####
  # xpectr::gxs_function(simplify_formula,
  #                      args_values = list(
  #                        "formula" = list(
  #                          "y ~ a * b + (1|c)",
  #                          "y * z ~ a * b + (1|c)",
  #                          " ~ a * b + (1|c)",
  #                          "a * b + (1|c) ~ ",
  #                          "a * b",
  #                          "y ~ 1",
  #                          "y ~ 1 + b",
  #                          "1 ~ y",
  #                          "1 + b ~ y",
  #                          "y ~ .",
  #                          "y + c ~ .",
  #                          "y ~ NULL",
  #                          "y ~ log(NULL)",
  #                          "NULL ~ a",
  #                          df,
  #                          NA,
  #                          3
  #                        ),
  #                        "data" = list(df, NA,
  #                                      list("a" = c(1, 2, 3, 4))),
  #                        "string_out" = list(TRUE)
  #                      ))
  # ####

  ## Testing 'simplify_formula'                                               ####
  ## Initially generated by xpectr
  # Testing different combinations of argument values

  # Testing simplify_formula(formula = "y * z ~ a * b + (1...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y * z ~ a * b + (1|c)", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y * z ~ a * b + (1|c)", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y * z ~ a * b + (1|c)", data = df, string_out = TRUE),
    "y + z ~ a + b + c",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y * z ~ a * b + (1|c)", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y * z ~ a * b + (1|c)", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y * z ~ a * b + (1|c)", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "y + c ~ .", data =...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y + c ~ .", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y + c ~ .", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y + c ~ .", data = df, string_out = TRUE),
    "y + c ~ a + b",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y + c ~ .", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y + c ~ .", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y + c ~ .", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "y ~ NULL", data = ...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y ~ NULL", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y ~ NULL", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y ~ NULL", data = df, string_out = TRUE),
    "y ~ NULL",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y ~ NULL", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y ~ NULL", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y ~ NULL", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "y ~ log(NULL)", da...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = "y ~ log(NULL)", data = df, string_out = TRUE)),
    xpectr::strip("the rhs of 'formula' did not contain any variables or allowed values."),
    fixed = TRUE)

  # Testing simplify_formula(formula = "NULL ~ a", data = ...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "NULL ~ a", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "NULL ~ a", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "NULL ~ a", data = df, string_out = TRUE),
    "NULL ~ a",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "NULL ~ a", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "NULL ~ a", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "NULL ~ a", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = df, data = df, stri...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = df, data = df, string_out = TRUE)),
    xpectr::strip(paste0("1 assertions failed:\n * Variable 'formula': Must be a formu",
           "la, not data.frame.")),
    fixed = TRUE)

  # Testing simplify_formula(formula = NA, data = df, stri...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = NA, data = df, string_out = TRUE)),
    xpectr::strip("1 assertions failed:\n * Variable 'formula': Must be a formula, not logical"),
    fixed = TRUE)

  # Testing simplify_formula(formula = 3, data = df, strin...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = 3, data = df, string_out = TRUE)),
    xpectr::strip(paste0("1 assertions failed:\n * Variable 'formula': Must be a formu",
                         "la, not double.")),
    fixed = TRUE)

  # Testing simplify_formula(formula = "y ~ a * b + (1|c)"...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = "y ~ a * b + (1|c)", data = NA, string_out = TRUE)),
    xpectr::strip(paste0("1 assertions failed:\n * Variable 'data': Must be of type 'd",
           "ata.frame' (or 'NULL'), not 'logical'.")),
    fixed = TRUE)

  # Testing simplify_formula(formula = "y ~ a * b + (1|c)"...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = "y ~ a * b + (1|c)", data = list(a = c(1, 2, 3, 4)), string_out = TRUE)),
    xpectr::strip(paste0("1 assertions failed:\n * Variable 'data': Must be of type 'd",
           "ata.frame' (or 'NULL'), not 'list'.")),
    fixed = TRUE)

  # Testing simplify_formula(formula = " ~ a * b + (1|c)",...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = " ~ a * b + (1|c)", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = " ~ a * b + (1|c)", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = " ~ a * b + (1|c)", data = df, string_out = TRUE),
    " ~ a + b + c",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = " ~ a * b + (1|c)", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = " ~ a * b + (1|c)", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = " ~ a * b + (1|c)", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "a * b + (1|c) ~ ",...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = "a * b + (1|c) ~ ", data = df, string_out = TRUE)),
    xpectr::strip(paste0("Could not convert 'formula' to a formula object. Got error:")),
    fixed = TRUE)

  # Testing simplify_formula(formula = "a * b", data = df,...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = "a * b", data = df, string_out = TRUE)),
    xpectr::strip(paste0("Could not convert 'formula' to a formula object. Got error:")),
    fixed = TRUE)

  # Testing simplify_formula(formula = "y ~ 1", data = df,...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y ~ 1", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y ~ 1", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y ~ 1", data = df, string_out = TRUE),
    "y ~ 1",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y ~ 1", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y ~ 1", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y ~ 1", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "y ~ 1 + b", data =...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y ~ 1 + b", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y ~ 1 + b", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y ~ 1 + b", data = df, string_out = TRUE),
    "y ~ b",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y ~ 1 + b", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y ~ 1 + b", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y ~ 1 + b", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "1 ~ y", data = df,...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "1 ~ y", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "1 ~ y", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "1 ~ y", data = df, string_out = TRUE),
    "1 ~ y",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "1 ~ y", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "1 ~ y", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "1 ~ y", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "1 + b ~ y", data =...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "1 + b ~ y", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "1 + b ~ y", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "1 + b ~ y", data = df, string_out = TRUE),
    "b ~ y",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "1 + b ~ y", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "1 + b ~ y", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "1 + b ~ y", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "y ~ .", data = df,...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y ~ .", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y ~ .", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y ~ .", data = df, string_out = TRUE),
    "y ~ a + b + c",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y ~ .", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y ~ .", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y ~ .", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "y ~ a * b + (1|c)"...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y ~ a * b + (1|c)", data = NULL, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y ~ a * b + (1|c)", data = NULL, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y ~ a * b + (1|c)", data = NULL, string_out = TRUE),
    "y ~ a + b + c",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y ~ a * b + (1|c)", data = NULL, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y ~ a * b + (1|c)", data = NULL, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y ~ a * b + (1|c)", data = NULL, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = "y ~ a * b + (1|c)"...
  # Testing class
  expect_equal(
    class(simplify_formula(formula = "y ~ a * b + (1|c)", data = df, string_out = TRUE)),
    "character",
    fixed = TRUE)
  # Testing type
  expect_type(
    simplify_formula(formula = "y ~ a * b + (1|c)", data = df, string_out = TRUE),
    type = "character")
  # Testing values
  expect_equal(
    simplify_formula(formula = "y ~ a * b + (1|c)", data = df, string_out = TRUE),
    "y ~ a + b + c",
    fixed = TRUE)
  # Testing names
  expect_equal(
    names(simplify_formula(formula = "y ~ a * b + (1|c)", data = df, string_out = TRUE)),
    NULL,
    fixed = TRUE)
  # Testing length
  expect_equal(
    length(simplify_formula(formula = "y ~ a * b + (1|c)", data = df, string_out = TRUE)),
    1L)
  # Testing sum of element lengths
  expect_equal(
    sum(xpectr::element_lengths(simplify_formula(formula = "y ~ a * b + (1|c)", data = df, string_out = TRUE))),
    1L)

  # Testing simplify_formula(formula = NULL, data = df, st...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = NULL, data = df, string_out = TRUE)),
    xpectr::strip(paste0("1 assertions failed:\n * Variable 'formula': Must be a formu",
                         "la, not NULL.")),
    fixed = TRUE)

  # Testing simplify_formula(formula = "y ~ a * b + (1|c)"...
  # Testing side effects
  expect_error(
    xpectr::strip_msg(simplify_formula(formula = "y ~ a * b + (1|c)", data = df, string_out = NULL)),
    xpectr::strip(paste0("1 assertions failed:\n * Variable 'string_out': Must be of t",
           "ype 'logical flag', not 'NULL'.")),
    fixed = TRUE)

  ## Finished testing 'simplify_formula'                                      ####


})
