from collections import namedtuple

from dal import autocomplete
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.views.generic import TemplateView

from shared.autocomplete import ModelSearch


class Select2QuerySetView(ModelSearch, autocomplete.Select2QuerySetView):
    """Compatibility layer between ModelSearch and Select2QuerySetView."""

    paginate_by = None

    def get_queryset(self):
        keywords = self.q.split()
        return super().search(keywords)


Section = namedtuple("Section", ("name", "verbose_name", "entries"))
Entry = namedtuple("Entry", ("verbose_name", "link"))


class AutocompleteView(TemplateView):
    template_name = "shared/search_results.html"
    search_composer = None

    def get_search_composer(self):
        if self.search_composer is None:
            raise ImproperlyConfigured("Please specify a search composer")
        return self.search_composer

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        if "q" not in self.request.GET:
            raise Http404
        q = self.request.GET["q"]
        ctx["q"] = q
        ctx["results"] = self.search(keywords=q.split())
        return ctx

    def search(self, keywords):
        search_composer = self.get_search_composer()
        raw_results = search_composer.search(keywords)
        sections = []
        for name, unit in search_composer.search_units:
            entries = [
                Entry(
                    verbose_name=unit.result_verbose_name(res),
                    link=unit.result_link(res),
                )
                for res in raw_results[name]
            ]
            if entries:
                sections.append(
                    Section(name=name, verbose_name=unit.verbose_name, entries=entries)
                )
        return sections
