"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 16.11.20

"""

from functools import wraps

from bootstrap_modal_forms.utils import is_ajax
from django.contrib import messages
from django.shortcuts import redirect, get_object_or_404, render
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from konova.utils.message_templates import MISSING_GROUP_PERMISSION, DATA_UNSHARED


def staff_required(function):
    """
    A decorator for functions which shall only be usable for staff members of the system
    """
    @wraps(function)
    def wrap(request, *args, **kwargs):
        user = request.user
        if user.is_staff:
            return function(request, *args, **kwargs)
        else:
            messages.info(request, _("You need to be staff to perform this action!"))
            return redirect(request.META.get("HTTP_REFERER", reverse("home")))
    return wrap


def superuser_required(function):
    """
    A decorator for functions which shall only be usable for superusers of the system
    """
    @wraps(function)
    def wrap(request, *args, **kwargs):
        user = request.user
        if user.is_superuser:
            return function(request, *args, **kwargs)
        else:
            messages.info(request, _("You need to be administrator to perform this action!"))
            return redirect(request.META.get("HTTP_REFERER", reverse("home")))
    return wrap


def any_group_check(function):
    """
    Checks for any group membership. Adds a message in case of having none.

    """
    @wraps(function)
    def wrap(request, *args, **kwargs):
        user = request.user
        # Inform user about missing group privileges!
        groups = user.groups.all()
        if not groups:
            messages.info(
                request,
                _("+++ Attention: You are not part of any group. You won't be able to create, edit or do anything. Please contact an administrator. +++")
            )
        return function(request, *args, **kwargs)
    return wrap


def default_group_required(function):
    """
    A decorator for functions which shall only be usable for users of specific groups.
    Group identifiers can be found in konova/settings.py

    """
    @wraps(function)
    def wrap(request, *args, **kwargs):
        user = request.user
        has_group = user.is_default_user()
        if has_group:
            return function(request, *args, **kwargs)
        else:
            messages.info(request, MISSING_GROUP_PERMISSION)
            return redirect(request.META.get("HTTP_REFERER", reverse("home")))
    return wrap


def registration_office_group_required(function):
    """
    A decorator for functions which shall only be usable for users of specific groups.
    Group identifiers can be found in konova/settings.py

    """
    @wraps(function)
    def wrap(request, *args, **kwargs):
        user = request.user
        has_group = user.is_zb_user()
        if has_group:
            return function(request, *args, **kwargs)
        else:
            messages.info(request, MISSING_GROUP_PERMISSION)
            return redirect(request.META.get("HTTP_REFERER", reverse("home")))
    return wrap


def conservation_office_group_required(function):
    """
    A decorator for functions which shall only be usable for users of specific groups.
    Group identifiers can be found in konova/settings.py

    """
    @wraps(function)
    def wrap(request, *args, **kwargs):
        user = request.user
        has_group = user.is_ets_user()
        if has_group:
            return function(request, *args, **kwargs)
        else:
            messages.info(request, MISSING_GROUP_PERMISSION)
            return redirect(request.META.get("HTTP_REFERER", reverse("home")))
    return wrap


def shared_access_required(obj_class, id_key):
    """ Checks whether the data is shared with the requesting user

    Args:
        obj_class (Model): The object/model class
        id_key (str): The name of the identifier attribute in **kwargs

    Returns:

    """
    def decorator(function):
        @wraps(function)
        def wrap(request, *args, **kwargs):
            user = request.user
            _id = kwargs.get(id_key, None)
            if _id is not None:
                obj = get_object_or_404(obj_class, id=_id)
                is_shared = obj.is_shared_with(user)
                if not is_shared:
                    messages.info(
                        request,
                        DATA_UNSHARED
                    )
                    return redirect("home")
            return function(request, *args, **kwargs)
        return wrap
    return decorator


def login_required_modal(function):
    """ Checks on modal requests whether the user is authenticated or not

    If not, the user will not be redirected but informed about the need to relogin.

    """
    @wraps(function)
    def wrap(request, *args, **kwargs):
        is_modal_request = is_ajax(request.META)
        is_user_not_logged_in = not request.user.is_authenticated

        if is_modal_request and is_user_not_logged_in:
            template = "modal/modal_generic.html"
            body_template = "modal/modal_session_timed_out.html"

            context = {
                "modal_body_template": body_template,
                "modal_title": _("Session timed out"),
            }
            return render(request, template, context)
        return function(request, *args, **kwargs)
    return wrap
