# -*- coding: utf-8 -*-
"""
    jinja2.asyncsupport
    ~~~~~~~~~~~~~~~~~~~

    Has all the code for async support which is implemented as a patch
    for supported Python versions.

    :copyright: (c) 2017 by the Jinja Team.
    :license: BSD, see LICENSE for more details.
"""
import sys
import asyncio
import inspect
from functools import update_wrapper

from jinja2.utils import concat, internalcode, Markup
from jinja2.environment import TemplateModule
from jinja2.runtime import LoopContextBase, _last_iteration


async def concat_async(async_gen):
    rv = []
    async def collect():
        async for event in async_gen:
            rv.append(event)
    await collect()
    return concat(rv)


async def generate_async(self, *args, **kwargs):
    vars = dict(*args, **kwargs)
    try:
        async for event in self.root_render_func(self.new_context(vars)):
            yield event
    except Exception:
        exc_info = sys.exc_info()
    else:
        return
    yield self.environment.handle_exception(exc_info, True)


def wrap_generate_func(original_generate):
    def _convert_generator(self, loop, args, kwargs):
        async_gen = self.generate_async(*args, **kwargs)
        try:
            while 1:
                yield loop.run_until_complete(async_gen.__anext__())
        except StopAsyncIteration:
            pass
    def generate(self, *args, **kwargs):
        if not self.environment.is_async:
            return original_generate(self, *args, **kwargs)
        return _convert_generator(self, asyncio.get_event_loop(), args, kwargs)
    return update_wrapper(generate, original_generate)


async def render_async(self, *args, **kwargs):
    if not self.environment.is_async:
        raise RuntimeError('The environment was not created with async mode '
                           'enabled.')

    vars = dict(*args, **kwargs)
    ctx = self.new_context(vars)

    try:
        return await concat_async(self.root_render_func(ctx))
    except Exception:
        exc_info = sys.exc_info()
    return self.environment.handle_exception(exc_info, True)


def wrap_render_func(original_render):
    def render(self, *args, **kwargs):
        if not self.environment.is_async:
            return original_render(self, *args, **kwargs)
        loop = asyncio.get_event_loop()
        return loop.run_until_complete(self.render_async(*args, **kwargs))
    return update_wrapper(render, original_render)


def wrap_block_reference_call(original_call):
    @internalcode
    async def async_call(self):
        rv = await concat_async(self._stack[self._depth](self._context))
        if self._context.eval_ctx.autoescape:
            rv = Markup(rv)
        return rv

    @internalcode
    def __call__(self):
        if not self._context.environment.is_async:
            return original_call(self)
        return async_call(self)

    return update_wrapper(__call__, original_call)


def wrap_macro_invoke(original_invoke):
    @internalcode
    async def async_invoke(self, arguments, autoescape):
        rv = await self._func(*arguments)
        if autoescape:
            rv = Markup(rv)
        return rv

    @internalcode
    def _invoke(self, arguments, autoescape):
        if not self._environment.is_async:
            return original_invoke(self, arguments, autoescape)
        return async_invoke(self, arguments, autoescape)
    return update_wrapper(_invoke, original_invoke)


@internalcode
async def get_default_module_async(self):
    if self._module is not None:
        return self._module
    self._module = rv = await self.make_module_async()
    return rv


def wrap_default_module(original_default_module):
    @internalcode
    def _get_default_module(self):
        if self.environment.is_async:
            raise RuntimeError('Template module attribute is unavailable '
                               'in async mode')
        return original_default_module(self)
    return _get_default_module


async def make_module_async(self, vars=None, shared=False, locals=None):
    context = self.new_context(vars, shared, locals)
    body_stream = []
    async for item in self.root_render_func(context):
        body_stream.append(item)
    return TemplateModule(self, context, body_stream)


def patch_template():
    from jinja2 import Template
    Template.generate = wrap_generate_func(Template.generate)
    Template.generate_async = update_wrapper(
        generate_async, Template.generate_async)
    Template.render_async = update_wrapper(
        render_async, Template.render_async)
    Template.render = wrap_render_func(Template.render)
    Template._get_default_module = wrap_default_module(
        Template._get_default_module)
    Template._get_default_module_async = get_default_module_async
    Template.make_module_async = update_wrapper(
        make_module_async, Template.make_module_async)


def patch_runtime():
    from jinja2.runtime import BlockReference, Macro
    BlockReference.__call__ = wrap_block_reference_call(
        BlockReference.__call__)
    Macro._invoke = wrap_macro_invoke(Macro._invoke)


def patch_filters():
    from jinja2.filters import FILTERS
    from jinja2.asyncfilters import ASYNC_FILTERS
    FILTERS.update(ASYNC_FILTERS)


def patch_all():
    patch_template()
    patch_runtime()
    patch_filters()


async def auto_await(value):
    if inspect.isawaitable(value):
        return await value
    return value


async def auto_aiter(iterable):
    if hasattr(iterable, '__aiter__'):
        async for item in iterable:
            yield item
        return
    for item in iterable:
        yield item


class AsyncLoopContext(LoopContextBase):

    def __init__(self, async_iterator, undefined, after, length, recurse=None,
                 depth0=0):
        LoopContextBase.__init__(self, undefined, recurse, depth0)
        self._async_iterator = async_iterator
        self._after = after
        self._length = length

    @property
    def length(self):
        if self._length is None:
            raise TypeError('Loop length for some iterators cannot be '
                            'lazily calculated in async mode')
        return self._length

    def __aiter__(self):
        return AsyncLoopContextIterator(self)


class AsyncLoopContextIterator(object):
    __slots__ = ('context',)

    def __init__(self, context):
        self.context = context

    def __aiter__(self):
        return self

    async def __anext__(self):
        ctx = self.context
        ctx.index0 += 1
        if ctx._after is _last_iteration:
            raise StopAsyncIteration()
        ctx._before = ctx._current
        ctx._current = ctx._after
        try:
            ctx._after = await ctx._async_iterator.__anext__()
        except StopAsyncIteration:
            ctx._after = _last_iteration
        return ctx._current, ctx


async def make_async_loop_context(iterable, undefined, recurse=None, depth0=0):
    # Length is more complicated and less efficient in async mode.  The
    # reason for this is that we cannot know if length will be used
    # upfront but because length is a property we cannot lazily execute it
    # later.  This means that we need to buffer it up and measure :(
    #
    # We however only do this for actual iterators, not for async
    # iterators as blocking here does not seem like the best idea in the
    # world.
    try:
        length = len(iterable)
    except (TypeError, AttributeError):
        if not hasattr(iterable, '__aiter__'):
            iterable = tuple(iterable)
            length = len(iterable)
        else:
            length = None
    async_iterator = auto_aiter(iterable)
    try:
        after = await async_iterator.__anext__()
    except StopAsyncIteration:
        after = _last_iteration
    return AsyncLoopContext(async_iterator, undefined, after, length, recurse,
                            depth0)
