from django.conf import settings
from django.http import HttpResponseForbidden, HttpResponseRedirect
try:
    from django.utils.translation import gettext as _
except:
    from django.utils.translation import ugettex as _
from django.urls import resolve

from django_roles_access.models import ViewAccess

DEFAULT_FORBIDDEN_MESSAGE = _(u'<h1>403 Forbidden</h1>')


def get_view_access(request):
    """
    Check access if exist a ViewAccess object for the view being processed.

    A ViewAccess object is linked to present view when current namespace and
    view name are the value of *view* attribute of the ViewAccess object. Can
    be only one ViewAccess object for each namespace and view name. If no
    namespace is used, application name is used instead as Django default
    behavior. This also means for Django < 2.0 the attribute app_name is
    required in URLConf (Django > 2.0 has this requirement).

    If exist a ViewAccess object linked to present view, security checks are
    done to conclude if request user have access or not. In case request user
    do not have access, PermissionDenied is raised.

    :return: True if user have access. Or raise PermissionDenied.
    """
    user = request.user
    current_url = resolve(request.path_info)
    view_name = current_url.view_name

    view_access = ViewAccess.objects.filter(view=view_name).first()
    if view_access:
        if view_access.type == 'pu':
            return True
        elif view_access.type == 'au':
            if user.is_authenticated:
                return True
            else:
                return False
        elif view_access.type == 'br':
            if user.is_authenticated:
                access = list(set(user.groups.all()) &
                              set(view_access.roles.all()))
                if access:
                    return True
                else:
                    return False
            else:
                return False
        else:
            return None


def get_setting_dictionary():
    """
    Return django-roles settings variable or None.

    :return: Dictionary with three keys: NOT_SECURE, PUBLIC, SECURE with their
             settings values or None.
    """
    settings_dictionary = {}

    try:
        settings_dictionary['NOT_SECURED'] = settings.NOT_SECURED
    except AttributeError:
        settings_dictionary['NOT_SECURED'] = []

    try:
        settings_dictionary['PUBLIC'] = settings.PUBLIC
    except AttributeError:
        settings_dictionary['PUBLIC'] = []

    try:
        settings_dictionary['SECURED'] = settings.SECURED
    except AttributeError:
        settings_dictionary['SECURED'] = []

    return settings_dictionary


def check_access_by_role(request):
    """
    Given a request to access a view the function check if user (logged or
    not) can access required view.

    :param request: :class:`django.http.HttpRequest`
    :return: True if can access the view. False in other case.
    """
    current_url = resolve(request.path_info)
    app_name = current_url.app_name
    setting_dictionary = get_setting_dictionary()

    # NOT_SECURED applications are ignored
    if app_name in setting_dictionary['NOT_SECURED']:
        return True
    # If view has an access configuration, this takes precedence over
    # the classification of the application
    view_access = get_view_access(request)
    if view_access is not None:
        return view_access
    # Check for public applications
    if app_name in setting_dictionary['PUBLIC']:
        return True
    if app_name in setting_dictionary['SECURED']:
        if not request.user.is_authenticated:
            return False
    return True


def get_app_type(app_name):
    for key, val in get_setting_dictionary().items():
        if app_name in val:
            return key
    return None


def get_forbidden_message():
    if hasattr(settings, 'DJANGO_ROLES_ACCESS_FORBIDDEN_MESSAGE'):
        return settings.DJANGO_ROLES_ACCESS_FORBIDDEN_MESSAGE
    return DEFAULT_FORBIDDEN_MESSAGE


def get_no_access_response():
    if hasattr(settings, 'DJANGO_ROLES_ACCESS_REDIRECT'):
        if settings.DJANGO_ROLES_ACCESS_REDIRECT:
            return HttpResponseRedirect(settings.LOGIN_URL)
    if hasattr(settings, 'DJANGO_ROLES_ACCESS_FORBIDDEN_MESSAGE'):
        return HttpResponseForbidden(
            settings.DJANGO_ROLES_ACCESS_FORBIDDEN_MESSAGE)
    return HttpResponseForbidden(DEFAULT_FORBIDDEN_MESSAGE)
