"""
    CAS login/logout replacement views
"""

import logging
from urllib import urlencode
from urlparse import urljoin

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseForbidden, HttpResponseRedirect

__all__ = [
    'login',
    'logout'
]
logger = logging.getLogger(
    __name__
)


def _service_url(
    request,
    redirect_to=None
):
    """
        Generates application service URL for CAS
    """

    protocol = ('http://', 'https://')[request.is_secure()]
    host = request.get_host()
    service = protocol + host + request.path
    if redirect_to:
        if '?' in service:
            service += '&'
        else:
            service += '?'
        service += urlencode({
            REDIRECT_FIELD_NAME: redirect_to
        })
    return service


def _redirect_url(
    request
):
    """
        Redirects to referring page, or CAS_REDIRECT_URL if no referrer is
        set.
    """

    next = request.GET.get(
        REDIRECT_FIELD_NAME
    )
    if not next:
        if settings.CAS_IGNORE_REFERER:
            next = settings.CAS_REDIRECT_URL
        else:
            next = request.META.get(
                'HTTP_REFERER',
                settings.CAS_REDIRECT_URL
            )
        prefix = (('http://', 'https://')[request.is_secure()] +
                  request.get_host())
        if next.startswith(prefix):
            next = next[len(prefix):]
    return next


def _login_url(
    service
):
    """
        Generates CAS login URL
    """

    params = {
        'service': service
    }
    if settings.CAS_EXTRA_LOGIN_PARAMS:
        params.update(
            settings.CAS_EXTRA_LOGIN_PARAMS
        )
    return urljoin(
        settings.CAS_SERVER_URL,
        'login'
    ) + '?' + urlencode(
        params
    )


def _logout_url(
    request,
    next_page=None
):
    """
        Generates CAS logout URL
    """

    if settings.CAS_LOGOUT_URL:
        url = settings.CAS_LOGOUT_URL
    else:
        url = urljoin(
            settings.CAS_SERVER_URL,
            'logout'
        )
    if next_page:
        protocol = ('http://', 'https://')[request.is_secure()]
        host = request.get_host()
        url += '?' + urlencode({
            'url': protocol + host + next_page
        })
    return url


def login(
    request,
    next_page=None,
    required=False
):
    """
        Forwards to CAS login URL or verifies CAS ticket
    """

    if not next_page:
        next_page = _redirect_url(
            request
        )
    if request.user.is_authenticated():
        if settings.CAS_DISPLAY_MESSAGES:
            message = "You are logged in as %s." % request.user.username
            messages.success(
                request,
                message
            )
        return HttpResponseRedirect(
            next_page
        )
    ticket = request.GET.get(
        'ticket'
    )
    service = _service_url(
        request,
        next_page
    )
    if ticket:
        from django.contrib import auth
        user = auth.authenticate(
            ticket=ticket,
            service=service,
            request=request
        )
        if user is not None:
            logger.debug(
                'Successfully authenticated %s' % user
            )
            auth.login(
                request,
                user
            )
            name = user.first_name or user.username
            message = "Login succeeded. Welcome, %s." % name
            messages.success(request, message)
            logger.debug(
                'Redirecting to ' + next_page
            )
            return HttpResponseRedirect(
                next_page
            )
        elif settings.CAS_RETRY_LOGIN or required:
            return HttpResponseRedirect(
                _login_url(
                    service
                )
            )
        elif settings.CAS_FAILURE_URL:
            return HttpResponseRedirect(
                settings.CAS_FAILURE_URL
            )
        else:
            error = "<h1>Forbidden</h1><p>Login failed.</p>"
            return HttpResponseForbidden(
                error
            )
    else:
        logger.debug(
            'User is not authenticated -- redirecting to CAS'
        )
        return HttpResponseRedirect(
            _login_url(
                service
            )
        )


def logout(
    request,
    next_page=None
):
    """
        Redirects to CAS logout page
    """
    from django.contrib.auth import logout as app_logout
    app_logout(
        request
    )
    if not next_page:
        next_page = _redirect_url(
            request
        )
    if settings.CAS_LOGOUT_COMPLETELY:
        return HttpResponseRedirect(
            _logout_url(
                request,
                next_page
            )
        )
    else:
        return HttpResponseRedirect(
            next_page
        )
