"""Test deltacycle._kernel.finish"""

from deltacycle import Kernel, create_task, finish, get_kernel, run, sleep, step

from .conftest import trace


async def ctl():
    trace("enter")
    await sleep(100)

    # Force all PING threads to stop immediately
    trace("finish")
    finish()


async def ping(period: int):
    trace("enter")
    while True:
        await sleep(period)
        trace("PING")


EXP1 = {
    # CTL
    (0, "CTL", "enter"),
    (100, "CTL", "finish"),
    # FOO
    (0, "FOO", "enter"),
    (3, "FOO", "PING"),
    (6, "FOO", "PING"),
    (9, "FOO", "PING"),
    (12, "FOO", "PING"),
    (15, "FOO", "PING"),
    (18, "FOO", "PING"),
    (21, "FOO", "PING"),
    (24, "FOO", "PING"),
    (27, "FOO", "PING"),
    (30, "FOO", "PING"),
    (33, "FOO", "PING"),
    (36, "FOO", "PING"),
    (39, "FOO", "PING"),
    (42, "FOO", "PING"),
    (45, "FOO", "PING"),
    (48, "FOO", "PING"),
    (51, "FOO", "PING"),
    (54, "FOO", "PING"),
    (57, "FOO", "PING"),
    (60, "FOO", "PING"),
    (63, "FOO", "PING"),
    (66, "FOO", "PING"),
    (69, "FOO", "PING"),
    (72, "FOO", "PING"),
    (75, "FOO", "PING"),
    (78, "FOO", "PING"),
    (81, "FOO", "PING"),
    (84, "FOO", "PING"),
    (87, "FOO", "PING"),
    (90, "FOO", "PING"),
    (93, "FOO", "PING"),
    (96, "FOO", "PING"),
    (99, "FOO", "PING"),
    # BAR
    (0, "BAR", "enter"),
    (5, "BAR", "PING"),
    (10, "BAR", "PING"),
    (15, "BAR", "PING"),
    (20, "BAR", "PING"),
    (25, "BAR", "PING"),
    (30, "BAR", "PING"),
    (35, "BAR", "PING"),
    (40, "BAR", "PING"),
    (45, "BAR", "PING"),
    (50, "BAR", "PING"),
    (55, "BAR", "PING"),
    (60, "BAR", "PING"),
    (65, "BAR", "PING"),
    (70, "BAR", "PING"),
    (75, "BAR", "PING"),
    (80, "BAR", "PING"),
    (85, "BAR", "PING"),
    (90, "BAR", "PING"),
    (95, "BAR", "PING"),
    # FIZ
    (0, "FIZ", "enter"),
    (7, "FIZ", "PING"),
    (14, "FIZ", "PING"),
    (21, "FIZ", "PING"),
    (28, "FIZ", "PING"),
    (35, "FIZ", "PING"),
    (42, "FIZ", "PING"),
    (49, "FIZ", "PING"),
    (56, "FIZ", "PING"),
    (63, "FIZ", "PING"),
    (70, "FIZ", "PING"),
    (77, "FIZ", "PING"),
    (84, "FIZ", "PING"),
    (91, "FIZ", "PING"),
    (98, "FIZ", "PING"),
    # BUZ
    (0, "BUZ", "enter"),
    (11, "BUZ", "PING"),
    (22, "BUZ", "PING"),
    (33, "BUZ", "PING"),
    (44, "BUZ", "PING"),
    (55, "BUZ", "PING"),
    (66, "BUZ", "PING"),
    (77, "BUZ", "PING"),
    (88, "BUZ", "PING"),
    (99, "BUZ", "PING"),
}


def test_finish1(captrace: set[tuple[int, str, str]]):
    async def main():
        create_task(ctl(), name="CTL")
        create_task(ping(3), name="FOO")
        create_task(ping(5), name="BAR")
        create_task(ping(7), name="FIZ")
        create_task(ping(11), name="BUZ")

    # Subsequent calls to run() have no effect
    run(main())

    kernel = get_kernel()
    assert kernel is not None
    assert kernel.state() is Kernel.State.FINISHED

    assert captrace == EXP1


def test_finish2(captrace: set[tuple[int, str, str]]):
    async def main():
        create_task(ctl(), name="CTL")
        create_task(ping(3), name="FOO")
        create_task(ping(5), name="BAR")
        create_task(ping(7), name="FIZ")
        create_task(ping(11), name="BUZ")

    # Subsequent calls to run() have no effect
    list(step(main()))

    kernel = get_kernel()
    assert kernel is not None
    assert kernel.state() is Kernel.State.FINISHED
    assert kernel.done()

    assert captrace == EXP1
