""" Collection of templatetags used accross the application."""

import re

from django import template

register = template.Library()


class NoSpacesNode(template.Node):
    """A template node that remove all spaces.

    Used by the ``nospaces`` templatetag.

    """

    spaces = re.compile(r'\s')

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

    def render(self, context):
        return self.spaces.sub('', self.nodelist.render(context).strip())


@register.tag
def nospaces(parser, token):  # pylint: disable=unused-argument
    """ Removes all whitespaces in the templatetag.

    Example
    -------

        <div class="{% nospaces %}
            {% if foo %}
                foo
            {% else %}
                bar
            {% endif %}
        {% endnospaces %}">


    This example would return this HTML::

        <div class="foo">

    """

    nodelist = parser.parse(('endnospaces',))
    parser.delete_first_token()
    return NoSpacesNode(nodelist)


class ReduceSpacesNode(template.Node):
    """A template node that remove all spaces.

    Used by the ``reducespaces`` templatetag.

    """
    spaces = re.compile(r'\s+')

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

    def render(self, context):
        return self.spaces.sub(' ', self.nodelist.render(context).strip())


@register.tag
def reducespaces(parser, token):  # pylint: disable=unused-argument
    """Replace many whitespace by one space in the templatetag.

    Example
    -------

        {% reducespaces %}
        <div
            class="foo
                   bar"
            id="baz"
            data-foo="bar"
            data-baz="qux"
        >
        {% endnospaces %}"


    This example would return this HTML::

        <div class="foo bar" id="baz" data-foo="bar" data-baz="qux" >
    """
    nodelist = parser.parse(('endreducespaces',))
    parser.delete_first_token()
    return ReduceSpacesNode(nodelist)


@register.simple_tag
def get_verbose_field_name(instance, field_name):
    """Returns the instance fields verbose_name."""
    return instance._meta.get_field(field_name).verbose_name.title()


@register.inclusion_tag('extras/pagination.html', takes_context=True)
def pagination(context, form_id=None):
    """Return the pagination template for the given context.

    Parameters
    ----------
    context: dict
        The template context.
    form_id: str (optional)
        Id of the form we want to submit while clicking on a pagination link
        When set, the given form will be submitted with an added "page"
        parameter. It was introduced to makge pagination works with
        django-filter forms.

    Returns
    -------
    dict
        A dict serving as context used to let `inclusion_tag` render the
        template `extras/pagination.html`.
        This dict contains:
        - is_paginated: bool
            `True` if the list is currently paginated (more than one page)
        - page_obj: Page
            A django paginator page representing the current page of the list
            on which we added two attributes:
            - previous_url: str
                The url to go to the previous page, if any
            - previous_number: int
                The number of the previous page (used when using buttons)
            - next_url: str
                The url to go to the next page, if any
            - next_number: int
                The number of the next page (used when using buttons)
        - view: View
            The current rendered view object
        - form_id: str
            The given form_id, used in the template to use buttons with
            the `form` attribute instead of normal links
    """

    is_paginated = bool(context.get('is_paginated', False))

    if not is_paginated:
        return {
            'is_paginated': is_paginated
        }

    page_obj = context['page_obj']
    page_obj.previous_url = None
    page_obj.previous_number = None
    page_obj.next_url = None
    page_obj.next_number = None

    if page_obj.has_previous():
        prev = context.request.GET.copy()
        page_obj.previous_number = page_obj.previous_page_number()
        prev['page'] = page_obj.previous_number
        page_obj.previous_url = prev.urlencode()

    if page_obj.has_next():
        next_page = context.request.GET.copy()
        page_obj.next_number = page_obj.next_page_number()
        next_page['page'] = page_obj.next_number
        page_obj.next_url = next_page.urlencode()

    return {
        'is_paginated': is_paginated,
        'page_obj': context['page_obj'],
        'view': context['view'],
        'form_id': form_id,
    }


@register.filter
def get_value(obj, key):
    """Filter to get the value of a dict or list according to a provided key.

    Parameters
    ----------
    obj: dict or list
        The object of which the value is extracted.
    key: str or int
        The key used to extract the value.

    """

    return obj[key]
