from functools import wraps

from . import filters
from .asyncsupport import auto_aiter
from .asyncsupport import auto_await


async def auto_to_seq(value):
    seq = []
    if hasattr(value, "__aiter__"):
        async for item in value:
            seq.append(item)
    else:
        for item in value:
            seq.append(item)
    return seq


async def async_select_or_reject(args, kwargs, modfunc, lookup_attr):
    seq, func = filters.prepare_select_or_reject(args, kwargs, modfunc, lookup_attr)
    if seq:
        async for item in auto_aiter(seq):
            if func(item):
                yield item


def dualfilter(normal_filter, async_filter):
    wrap_evalctx = False
    if getattr(normal_filter, "environmentfilter", False) is True:

        def is_async(args):
            return args[0].is_async

        wrap_evalctx = False
    else:
        has_evalctxfilter = getattr(normal_filter, "evalcontextfilter", False) is True
        has_ctxfilter = getattr(normal_filter, "contextfilter", False) is True
        wrap_evalctx = not has_evalctxfilter and not has_ctxfilter

        def is_async(args):
            return args[0].environment.is_async

    @wraps(normal_filter)
    def wrapper(*args, **kwargs):
        b = is_async(args)
        if wrap_evalctx:
            args = args[1:]
        if b:
            return async_filter(*args, **kwargs)
        return normal_filter(*args, **kwargs)

    if wrap_evalctx:
        wrapper.evalcontextfilter = True

    wrapper.asyncfiltervariant = True

    return wrapper


def asyncfiltervariant(original):
    def decorator(f):
        return dualfilter(original, f)

    return decorator


@asyncfiltervariant(filters.do_first)
async def do_first(environment, seq):
    try:
        return await auto_aiter(seq).__anext__()
    except StopAsyncIteration:
        return environment.undefined("No first item, sequence was empty.")


@asyncfiltervariant(filters.do_groupby)
async def do_groupby(environment, value, attribute):
    expr = filters.make_attrgetter(environment, attribute)
    return [
        filters._GroupTuple(key, await auto_to_seq(values))
        for key, values in filters.groupby(
            sorted(await auto_to_seq(value), key=expr), expr
        )
    ]


@asyncfiltervariant(filters.do_join)
async def do_join(eval_ctx, value, d="", attribute=None):
    return filters.do_join(eval_ctx, await auto_to_seq(value), d, attribute)


@asyncfiltervariant(filters.do_list)
async def do_list(value):
    return await auto_to_seq(value)


@asyncfiltervariant(filters.do_reject)
async def do_reject(*args, **kwargs):
    return async_select_or_reject(args, kwargs, lambda x: not x, False)


@asyncfiltervariant(filters.do_rejectattr)
async def do_rejectattr(*args, **kwargs):
    return async_select_or_reject(args, kwargs, lambda x: not x, True)


@asyncfiltervariant(filters.do_select)
async def do_select(*args, **kwargs):
    return async_select_or_reject(args, kwargs, lambda x: x, False)


@asyncfiltervariant(filters.do_selectattr)
async def do_selectattr(*args, **kwargs):
    return async_select_or_reject(args, kwargs, lambda x: x, True)


@asyncfiltervariant(filters.do_map)
async def do_map(*args, **kwargs):
    seq, func = filters.prepare_map(args, kwargs)
    if seq:
        async for item in auto_aiter(seq):
            yield await auto_await(func(item))


@asyncfiltervariant(filters.do_sum)
async def do_sum(environment, iterable, attribute=None, start=0):
    rv = start
    if attribute is not None:
        func = filters.make_attrgetter(environment, attribute)
    else:

        def func(x):
            return x

    async for item in auto_aiter(iterable):
        rv += func(item)
    return rv


@asyncfiltervariant(filters.do_slice)
async def do_slice(value, slices, fill_with=None):
    return filters.do_slice(await auto_to_seq(value), slices, fill_with)


ASYNC_FILTERS = {
    "first": do_first,
    "groupby": do_groupby,
    "join": do_join,
    "list": do_list,
    # we intentionally do not support do_last because it may not be safe in async
    "reject": do_reject,
    "rejectattr": do_rejectattr,
    "map": do_map,
    "select": do_select,
    "selectattr": do_selectattr,
    "sum": do_sum,
    "slice": do_slice,
}
