from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views.generic import FormView
from django.views.generic.detail import SingleObjectMixin

from judge.utils.diggpaginator import DiggPaginator
from django.utils.html import mark_safe


def class_view_decorator(function_decorator):
    """Convert a function based decorator into a class based decorator usable
    on class based Views.

    Can't subclass the `View` as it breaks inheritance (super in particular),
    so we monkey-patch instead.
    """

    def simple_decorator(View):
        View.dispatch = method_decorator(function_decorator)(View.dispatch)
        return View

    return simple_decorator


def generic_message(request, title, message, status=None):
    return render(
        request,
        "generic-message.html",
        {
            "message": message,
            "title": title,
        },
        status=status,
    )


def paginate_query_context(request):
    query = request.GET.copy()
    query.setlist("page", [])
    query = query.urlencode()
    if query:
        return {
            "page_prefix": "%s?%s&page=" % (request.path, query),
            "first_page_href": "%s?%s" % (request.path, query),
        }
    else:
        return {
            "page_prefix": "%s?page=" % request.path,
            "first_page_href": request.path,
        }


class TitleMixin(object):
    title = "(untitled)"
    content_title = None

    def get_context_data(self, **kwargs):
        context = super(TitleMixin, self).get_context_data(**kwargs)
        context["title"] = self.get_title()
        content_title = self.get_content_title()
        if content_title is not None:
            context["content_title"] = content_title
        return context

    def get_content_title(self):
        return self.content_title

    def get_title(self):
        return self.title


class DiggPaginatorMixin(object):
    def get_paginator(
        self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs
    ):
        return DiggPaginator(
            queryset,
            per_page,
            body=6,
            padding=2,
            orphans=orphans,
            allow_empty_first_page=allow_empty_first_page,
            **kwargs
        )


class QueryStringSortMixin(object):
    all_sorts = None
    default_sort = None
    default_desc = ()

    def get_default_sort_order(self, request):
        return self.default_sort

    def get(self, request, *args, **kwargs):
        order = request.GET.get("order", "")
        if not (
            (not order.startswith("-") or order.count("-") == 1)
            and (order.lstrip("-") in self.all_sorts)
        ):
            order = self.get_default_sort_order(request)
        self.order = order

        return super(QueryStringSortMixin, self).get(request, *args, **kwargs)

    def get_sort_context(self):
        query = self.request.GET.copy()
        query.setlist("order", [])
        query = query.urlencode()
        sort_prefix = (
            "%s?%s&order=" % (self.request.path, query)
            if query
            else "%s?order=" % self.request.path
        )
        current = self.order.lstrip("-")

        links = {
            key: sort_prefix + ("-" if key in self.default_desc else "") + key
            for key in self.all_sorts
        }
        links[current] = (
            sort_prefix + ("" if self.order.startswith("-") else "-") + current
        )

        order = {key: "" for key in self.all_sorts}
        order[current] = " \u25BE" if self.order.startswith("-") else " \u25B4"
        return {"sort_links": links, "sort_order": order}

    def get_sort_paginate_context(self):
        return paginate_query_context(self.request)


def short_circuit_middleware(view):
    view.short_circuit_middleware = True
    return view


class SingleObjectFormView(SingleObjectMixin, FormView):
    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super().post(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super().get(request, *args, **kwargs)