import asyncio
from functools import partial

import pytest

from busypie import ConditionTimeoutError, wait
from tests.sleeper import AsyncSleeper


@pytest.fixture
def sleeper():
    yield AsyncSleeper()


@pytest.mark.asyncio
async def test_wait_until_done(sleeper):
    await asyncio.gather(
        wait_until_awake(sleeper),
        sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_wait_with_async_condition(sleeper):
    await asyncio.gather(
        async_wait_until_awake(sleeper),
        sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_wait_during_not_done(sleeper):
    await asyncio.gather(
        wait_during_sleep(sleeper),
        sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_wait_fail_on_timeout(sleeper):
    with pytest.raises(ConditionTimeoutError):
        await asyncio.gather(
            async_wait_until_awake(sleeper, delay=0.6),
            sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_retrieve_condition_result(sleeper):
    assert await wait().until_async(return_12) == 12


async def wait_until_awake(sleeper):
    await wait().at_most(AsyncSleeper.SLEEP_DURATION + 0.1).until_async(lambda: sleeper.awake)
    assert sleeper.awake


async def wait_during_sleep(sleeper):
    await wait().at_most(AsyncSleeper.SLEEP_DURATION + 0.1).during_async(lambda: not sleeper.awake)
    assert sleeper.awake


async def async_wait_until_awake(sleeper, delay=0.01):
    await wait().at_most(AsyncSleeper.SLEEP_DURATION + 0.1).until_async(partial(sleeper.get_awake_with_delay, delay))
    assert sleeper.awake


async def return_12():
    return 12

import asyncio
from functools import partial

import pytest

from busypie import ConditionTimeoutError, wait
from tests.sleeper import AsyncSleeper


@pytest.fixture
def sleeper():
    yield AsyncSleeper()


@pytest.mark.asyncio
async def test_wait_until_done(sleeper):
    await asyncio.gather(
        wait_until_awake(sleeper),
        sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_wait_with_async_condition(sleeper):
    await asyncio.gather(
        async_wait_until_awake(sleeper),
        sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_wait_during_not_done(sleeper):
    await asyncio.gather(
        wait_during_sleep(sleeper),
        sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_wait_fail_on_timeout(sleeper):
    with pytest.raises(ConditionTimeoutError):
        await asyncio.gather(
            async_wait_until_awake(sleeper, delay=0.6),
            sleeper.sleep_for_a_bit())


@pytest.mark.asyncio
async def test_retrieve_condition_result(sleeper):
    assert await wait().until_async(return_12) == 12


async def wait_until_awake(sleeper):
    await wait().at_most(AsyncSleeper.SLEEP_DURATION + 0.1).until_async(lambda: sleeper.awake)
    assert sleeper.awake


async def wait_during_sleep(sleeper):
    await wait().at_most(AsyncSleeper.SLEEP_DURATION + 0.1).during_async(lambda: not sleeper.awake)
    assert sleeper.awake


async def async_wait_until_awake(sleeper, delay=0.01):
    await wait().at_most(AsyncSleeper.SLEEP_DURATION + 0.1).until_async(partial(sleeper.get_awake_with_delay, delay))
    assert sleeper.awake


async def return_12():
    return 12
