"""Page CMS functions related to the ``request`` object."""
from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import WSGIRequest
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core.urlresolvers import reverse
from pages import settings

def get_request_mock():
    """Build a ``request`` mock that can be used for testing."""
    basehandler = BaseHandler()
    basehandler.load_middleware()
    request = WSGIRequest({
        'REQUEST_METHOD': 'GET',
        'SERVER_NAME': 'test',
        'SERVER_PORT': '8000',
        'HTTP_HOST': 'testhost',
    })
    # Apply request middleware
    for middleware_method in basehandler._request_middleware:
        # LocaleMiddleware should never be applied a second time because
        # it would broke the current real request language
        if 'LocaleMiddleware' not in str(middleware_method.im_class):
            response = middleware_method(request)
    return request

class AutoRenderHttpError(Exception):
    """Cannot return context dictionary because a view returned an
    ``HttpResponse`` when a (template_name, context) tuple was expected."""
    pass

def auto_render(func):
    """
    This view decorator automatically calls the ``render_to_response``
    shortcut. A view that use this decorator should return a tuple of this
    form : (template name, context) instead of a ``HttpRequest`` object.
    """
    def _dec(request, *args, **kwargs):
        template_override = kwargs.pop('template_name', None)
        only_context = kwargs.pop('only_context', False)
        only_response = kwargs.pop('only_response', False)
        if only_context or only_response:
            # return only context dictionary or response
            response = func(request, *args, **kwargs)
            if only_response:
                return response
            if isinstance(response, HttpResponse):
                raise AutoRenderHttpError
            (template_name, context) = response
            return context
        response = func(request, *args, **kwargs)
        if isinstance(response, HttpResponse):
            return response
        (template_name, context) = response
        template_name = context['template_name'] = template_override or template_name
        return render_to_response(template_name, context,
                            context_instance=RequestContext(request))
    return _dec

def pages_view(view):
    """
    Provide the pages variables to the decorated view.
    """
    def _dec(request, *args, **kwargs):
        path = kwargs.pop('path', None)
        lang = kwargs.pop('lang', None)
        if path or lang:
            from pages.views import details
            response = details(request, path=path, lang=lang,
                only_context=True, delegation=False)
            context = response
            kwargs.update(context)
        return view(request, *args, **kwargs)
    return _dec


def get_slug_and_relative_path(path, lang=None):
    """Return the page's slug and relative path."""
    root = reverse('pages-root')
    if path.startswith(root):
        path = path[len(root):]
    if len(path) and path[-1] == '/':
        path = path[:-1]
    slug = path.split("/")[-1]
    if settings.PAGE_USE_LANGUAGE_PREFIX:
        lang = path.split("/")[0]
        path = path[(len(lang) + 1):]
    return slug, path, lang

def get_template_from_request(request, page=None):
    """
    Gets a valid template from different sources or falls back to the
    default template.
    """
    page_templates = settings.get_page_templates()
    if len(page_templates) == 0:
        return settings.PAGE_DEFAULT_TEMPLATE
    template = request.REQUEST.get('template', None)
    if template is not None and \
            (template in dict(page_templates).keys() or
            template == settings.PAGE_DEFAULT_TEMPLATE):
        return template
    if page is not None:
        return page.get_template()
    return settings.PAGE_DEFAULT_TEMPLATE

def get_language_from_request(request):
    """Return the most obvious language according the request."""
    language = request.GET.get('language', None)
    if language:
        return language

    if hasattr(request, 'LANGUAGE_CODE'):
        return settings.PAGE_LANGUAGE_MAPPING(str(request.LANGUAGE_CODE))
    else:
        return settings.PAGE_DEFAULT_LANGUAGE

