require("test/setup")
require("action-queue")

function testActionQueueRunsToCompletion()
    actionQueue.queue = {}
    local invokeTotalSec = 0
    local hasYielded = false
    actionQueue:upsert("testAction", 9999999999, function(delta)
        while invokeTotalSec < 5 do
            invokeTotalSec = invokeTotalSec + delta
            hasYielded = true
            coroutine.yield()
        end
    end)
    luaunit.assertIsFalse(hasYielded, "Should not have been invoked yet.")
    for _ = 1, 10 do
        actionQueue:runWaiting(1)
        luaunit.assertIsTrue(hasYielded, "Should have been invoked.")
    end
    luaunit.assertEquals(5, invokeTotalSec, "Should have run five times and stopped itself")
end

function testActionQueueExpiration()
    actionQueue.queue = {}
    local yieldCount = 0
    actionQueue:upsert("testAction", 2000, function()
        while true do
            yieldCount = yieldCount + 1
            coroutine.yield()
        end
    end)

    local skipSec = 60
    playdate.skipMs(60 * 1000)
    actionQueue:runWaiting(skipSec)
    luaunit.assertEquals(1, yieldCount, "Should always be invoked at least once")

    playdate.skipMs(1000)
    actionQueue:runWaiting(1)
    luaunit.assertEquals(1, yieldCount, "Should not be invoked again after expiry")
end

function testDuplicateUpsertsShouldOnlyRunOnce()
    actionQueue.queue = {}
    local yieldCount = 0
    local yieldId
    local action = function(id)
        return function()
            while true do
                yieldCount = yieldCount + 1
                yieldId = id
                coroutine.yield()
            end
        end
    end

    for i = 1, 10 do
        actionQueue:upsert("testAction", 9999999999, action(i))
    end
    actionQueue:runWaiting(1)
    luaunit.assertEquals(1, yieldCount, "Duplicate upserts should result in only one invocation.")
    luaunit.assertEquals(10, yieldId, "Most recent upsert should take precedence.")
end

function testNewOnlyActionsShouldNotReplaceExistingActions()
    actionQueue.queue = {}
    local yieldCount = 0
    local yieldId
    local action = function(id)
        return function()
            while true do
                yieldCount = yieldCount + 1
                yieldId = id
                coroutine.yield()
            end
        end
    end

    for i = 1, 10 do
        actionQueue:newOnly("testAction", 9999999999, action(i))
    end
    actionQueue:runWaiting(1)
    luaunit.assertEquals(1, yieldCount, "Duplicate newOnly should result in only one invocation.")
    luaunit.assertEquals(1, yieldId, "The first newOnly should take precedence.")
end

os.exit(luaunit.LuaUnit.run())
