"""
Functions that are not clearly related to another module
"""
import asyncio
import inspect
from typing import Awaitable, List, TypeVar, Union

Result = TypeVar("Result")


async def gather_if_necessary(results_and_awaitable_results: List[Union[Result, Awaitable[Result]]]) -> List[Result]:
    """
    Await the awaitables, pass the un-awaitable results
    :param results_and_awaitable_results: heterogenous list of both Ts and Awaitable[T]s.
    :return: list of T in the same order as in the input param.
    """
    awaitable_indexes = [n for n, x in enumerate(results_and_awaitable_results) if inspect.isawaitable(x)]
    awaited_results = await asyncio.gather(*[x for x in results_and_awaitable_results if inspect.isawaitable(x)])
    result: List[Result] = []
    awaited_results_index = 0
    for index, obj in enumerate(results_and_awaitable_results):
        if index in awaitable_indexes:
            result.append(awaited_results[awaited_results_index])
            awaited_results_index += 1
        else:
            # we are sure obj is of type T
            result.append(obj)  # type:ignore[arg-type]
    return result
