context("Multiset Combinations")

test_that("Multiset Combinations - ncombinations", {
    expect_equal(ncombinations(freq = c(2, 3, 3, 4), k = 4), 29)
    expect_equal(ncombinations(x = LETTERS[1:4], freq = c(2, 3, 3, 4), k = 4), 29)
    expect_error(ncombinations(freq = rep(10, 11), k = 50), "integer overflow")
    expect_error(ncombinations(x = LETTERS[1:11], freq = rep(10, 11), k = 50), "integer overflow")
    expect_equal(ncombinations(freq = rep(10, 11), k = 50, bigz = TRUE), gmp::as.bigz("9608991865"))
    expect_equal(ncombinations(freq = c(0, 0, 0), k = 4), 0)
    expect_equal(ncombinations(freq = c(0, 0, 0), k = 0), 1)
    expect_error(ncombinations(freq = c(2, 3, 3, 4), k = -1), "expect integer")
    expect_error(ncombinations(freq = c(2, 3, 3, 4), k = 1.5), "expect integer")
})

test_that("Multiset Combinations - combinations", {
    comb <- combinations(freq = c(2, 3, 3, 4), k = 4)
    expect_equal(nrow(comb), 29)
    expect_equal(ncol(comb), 4)
    expect_equal(comb[1, ], c(1, 1, 2, 2))
    expect_equal(comb[29, ], rep(4, 4))

    comb <- combinations(freq = c(2, 3, 3, 4), k = 4, layout = "row")
    expect_equal(nrow(comb), 29)
    expect_equal(ncol(comb), 4)
    expect_equal(comb[1, ], c(1, 1, 2, 2))
    expect_equal(comb[29, ], rep(4, 4))

    comb <- combinations(freq = c(2, 3, 3, 4), k = 4, layout = "column")
    expect_equal(ncol(comb), 29)
    expect_equal(nrow(comb), 4)
    expect_equal(comb[, 1], c(1, 1, 2, 2))
    expect_equal(comb[, 29], rep(4, 4))

    comb <- combinations(freq = c(2, 3, 3, 4), k = 4, layout = "list")
    expect_equal(length(comb), 29)
    expect_equal(comb[[1]], c(1, 1, 2, 2))
    expect_equal(comb[[29]], rep(4, 4))

    comb <- combinations(x = LETTERS[1:4], freq = c(2, 3, 3, 4), k = 4)
    expect_equal(nrow(comb), 29)
    expect_equal(ncol(comb), 4)
    expect_equal(comb[1, ], LETTERS[c(1, 1, 2, 2)])
    expect_equal(comb[29, ], LETTERS[rep(4, 4)])

    expect_error(combinations(freq = rep(10, 11), k = 50), "too many results")
    expect_error(combinations(freq = c(2, 3, 3, 4), k = -1), "expect integer")
    expect_error(combinations(freq = c(2, 3, 3, 4), k = 1.5), "expect integer")
    expect_equal(dim(combinations(freq = c(2, 3, 3, 4), k = 0)), c(1, 0))
    expect_equal(dim(combinations(freq = c(0, 0, 0), k = 1 )), c(0, 1))
    expect_equal(dim(combinations(freq = c(0, 0, 0), k = 0 )), c(1, 0))
})

test_that("Multiset Combinations - icombinations", {
    icomb <- icombinations(freq = c(2, 3, 3, 4), k = 4)
    comb <- combinations(freq = c(2, 3, 3, 4), k = 4)
    expect_equal(icomb$collect(), comb)
    expect_equal(icomb$getnext(), c(1, 1, 2, 2))
    expect_equal(icomb$getnext(), c(1, 1, 2, 3))
    icomb$getnext(20)
    expect_equal(nrow(icomb$getnext(10)), 7)
    expect_equal(icomb$getnext(), NULL)

    comb <- combinations(freq = c(2, 3, 3, 4), k = 4, layout = "row")
    expect_equal(icomb$collect(layout = "row"), comb)
    expect_equal(icomb$getnext(layout = "row"), t(c(1, 1, 2, 2)))
    expect_equal(icomb$getnext(layout = "row"), t(c(1, 1, 2, 3)))
    icomb$getnext(20, layout = "row")
    expect_equal(nrow(icomb$getnext(10, layout = "row")), 7)
    expect_equal(icomb$getnext(layout = "row"), NULL)

    comb <- combinations(freq = c(2, 3, 3, 4), k = 4, layout = "column")
    expect_equal(icomb$collect(layout = "column"), comb)
    expect_equal(icomb$getnext(layout = "column"), t(t(c(1, 1, 2, 2))))
    expect_equal(icomb$getnext(layout = "column"), t(t(c(1, 1, 2, 3))))
    icomb$getnext(20, layout = "column")
    expect_equal(ncol(icomb$getnext(10, layout = "column")), 7)
    expect_equal(icomb$getnext(layout = "column"), NULL)

    comb <- combinations(freq = c(2, 3, 3, 4), k = 4, layout = "list")
    expect_equal(icomb$collect(layout = "list"), comb)
    expect_equal(icomb$getnext(layout = "list"), list(c(1, 1, 2, 2)))
    expect_equal(icomb$getnext(layout = "list"), list(c(1, 1, 2, 3)))
    icomb$getnext(20, layout = "list")
    expect_equal(length(icomb$getnext(10, layout = "list")), 7)
    expect_equal(icomb$getnext(layout = "list"), NULL)

    expect_error(icombinations(freq = c(2, 3, 3, 4), k = -1), "expect integer")
    expect_error(icombinations(freq = c(2, 3, 3, 4), k = 1.5), "expect integer")
    icomb <- icombinations(freq = c(2, 3, 3, 4), k = 0)
    expect_equal(dim(icomb$collect()), c(1, 0))
    expect_equal(icomb$getnext(), integer(0))
    icomb <- icombinations(freq = c(2, 3, 3, 4), k = 13)
    expect_equal(dim(icomb$collect()), c(0, 13))
    expect_equal(icomb$getnext(), NULL)
})

test_that("Multiset Combinations - index", {
    comb <- combinations(freq = c(2, 3, 3, 4), k = 4)
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, index = 1:29), comb)
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, index = as.numeric(1:29)), comb)
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, index = as.character(1:29)), comb)
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, index = gmp::as.bigz(1:29)), comb)
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, index = 2), c(1, 1, 2, 3))
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, index = 29), c(4, 4, 4, 4))
    expect_equal(combinations(freq = rep(10, 11), k = 50, index = 2), c(rep(1:4, each = 10), rep(5, 9), 6))
    expect_equal(combinations(freq = rep(10, 11), k = 50, index = "9608991865"), rep(7:11, each = 10))

    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 0, index = 1), integer(0))
    expect_equal(combinations(freq = 0, k = 0, index = 1), integer(0))
    expect_error(combinations(freq = 0, k = 1, index = 1), "invalid index")
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 0, index = gmp::as.bigz(1)), integer(0))
    expect_equal(combinations(freq = 0, k = 0, index = gmp::as.bigz(1)), integer(0))
    expect_error(combinations(freq = 0, k = 1, index = gmp::as.bigz(1)), "invalid index")
})

test_that("Multiset Combinations - skip", {
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, skip = 29), combinations(freq = c(2, 3, 3, 4), k = 4))
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, skip = 3), combinations(freq = c(2, 3, 3, 4), k = 4)[4:29, ])
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, skip = 3, nitem = 4), combinations(freq = c(2, 3, 3, 4), k = 4)[4:7, ])
    expect_equal(combinations(freq = c(2, 3, 3, 4), k = 4, skip = gmp::as.bigz(3), nitem = 4), combinations(freq = c(2, 3, 3, 4), k = 4)[4:7, ])
})
