"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: ksp-servicestelle@sgdnord.rlp.de
Created on: 18.08.22

"""
from dal_select2.views import Select2GroupQuerySetView
from django.db.models import Q

from codelist.models import KonovaCode


class KonovaCodeAutocomplete(Select2GroupQuerySetView):
    """
    Provides simple autocomplete functionality for codes

    Parameter support:
    * q: Search for a word inside long_name of a code
    * c: Search inside a special codelist

    """
    paginate_by = 50

    def order_by(self, qs):
        """ Orders by a predefined value

        Wrapped in a function to provide inheritance-based different orders

        Args:
            qs (QuerySet): The queryset to be ordered

        Returns:
            qs (QuerySet): The ordered queryset
        """
        return qs.order_by(
            "long_name"
        )

    def get_queryset(self):
        if self.request.user.is_anonymous:
            return KonovaCode.objects.none()
        qs = KonovaCode.objects.filter(
            is_archived=False,
            is_selectable=True,
            is_leaf=True,
        )
        qs = self.order_by(qs)
        if self.c:
            qs = qs.filter(
                code_lists__in=[self.c]
            )
        if self.q:
            # Remove whitespaces from self.q and split input in all keywords (if multiple given)
            q = dict.fromkeys(self.q.strip().split(" "))
            # Create one filter looking up for all keys where all keywords can be found in the same result
            _filter = Q()
            for keyword in q:
                q_or = Q()
                q_or |= Q(long_name__icontains=keyword)
                q_or |= Q(short_name__icontains=keyword)
                q_or |= Q(parent__long_name__icontains=keyword)
                q_or |= Q(parent__short_name__icontains=keyword)
                q_or |= Q(parent__parent__long_name__icontains=keyword)
                q_or |= Q(parent__parent__short_name__icontains=keyword)
                _filter.add(q_or, Q.AND)
            qs = qs.filter(_filter).distinct()
        return qs

    def get_result_label(self, result):
        return f"{result.long_name}"

    def get_selected_result_label(self, result):
        return f"{result.__str__()}"
