import asyncio
import time


async def cook_sushi():
    """sushiを握るのには3秒または7秒かかる"""
    print('sushi職人「sushi一丁！」')
    await asyncio.sleep(sushi_cook_time)
    print('sushi職人「sushiお待ち！」')
    return "sushi"


async def cook_miso():
    """misoは1秒でできる"""
    print('sushi職人「miso一丁！」')
    await asyncio.sleep(1)
    print('sushi職人「misoお待ち！」')
    return "miso"


def eat(dish):
    print(f"客「{dish}うまあ😋」")


async def case1():
    """Case1: 寿司も味噌汁も頼んでおとなしく待ち、来た順に食う"""
    for future in asyncio.as_completed([cook_sushi(), cook_miso()]):
        result = await future
        eat(result)

    return None


async def case2():
    """Case2: 寿司を頼んでから5秒かかっても来なかったら店を出る"""
    try:
        result = await asyncio.wait_for(cook_sushi(), timeout=5.0)
        eat(result)
    except asyncio.TimeoutError:
        print('客「sushiが来ないなら帰らせて頂く」')
    return None


async def case3():
    """Case3: 寿司を頼んでから5秒かかっても来なかったら味噌汁を頼む"""
    done, pending = await asyncio.wait(
        [cook_sushi(), asyncio.sleep(5)], return_when=asyncio.FIRST_COMPLETED)
    for d in done:
        result = d.result()
        if result == 'sushi':
            eat(result)
        else:
            # sushi が来なかった場合 (asyncio.sleep(5)の戻り値は None)
            result = await cook_miso()
            eat(result)
            if len(pending) > 0:
                done, pending = await asyncio.wait(
                    pending, return_when=asyncio.ALL_COMPLETED)
                for d in done:
                    eat(d.result())


if __name__ == '__main__':
    #sushi_cook_time = 3
    sushi_cook_time = 7

    loop = asyncio.get_event_loop()
    print(case1.__doc__)
    time.sleep(1)
    result = loop.run_until_complete(case1())
    print('')
    print(case2.__doc__)
    time.sleep(1)
    result = loop.run_until_complete(case2())
    print('')
    print(case3.__doc__)
    time.sleep(1)
    result = loop.run_until_complete(case3())