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

"""
from django import forms
from django.db.models import QuerySet, Q
from django.utils.translation import gettext_lazy as _
import django_filters

from konova.models import Parcel, District


class GeoReferencedTableFilterMixin(django_filters.FilterSet):
    """ A mixin for AbstractTableFilter

    Specialized on filtering GeoReferenced model types

    """
    # District
    di = django_filters.CharFilter(
        method="filter_district",
        label=_(""),
        label_suffix=_(""),
        widget=forms.TextInput(
            attrs={
                "placeholder": _("District"),
                "title": _("Search for district"),
                "class": "form-control",
            }
        ),
    )
    # Parcel gmrkng
    pg = django_filters.CharFilter(
        method="filter_gmrkng",
        label=_(""),
        label_suffix=_(""),
        widget=forms.TextInput(
            attrs={
                "placeholder": _("Parcel gmrkng"),
                "title": _("Search for parcel gmrkng"),
                "class": "form-control",
            }
        ),
    )
    # Parcel
    p = django_filters.NumberFilter(
        method="filter_parcel",
        label=_(""),
        label_suffix=_(""),
        widget=forms.TextInput(
            attrs={
                "placeholder": _("Parcel"),
                "title": _("Search for parcel"),
                "class": "form-control",
            }
        ),
    )
    # Parcel counter
    pc = django_filters.NumberFilter(
        method="filter_parcel_counter",
        label=_(""),
        label_suffix=_(""),
        widget=forms.TextInput(
            attrs={
                "placeholder": _("Parcel counter"),
                "title": _("Search for parcel counter"),
                "class": "form-control",
            }
        ),
    )

    # Parcel number
    pn = django_filters.NumberFilter(
        method="filter_parcel_number",
        label=_(""),
        label_suffix=_(""),
        widget=forms.TextInput(
            attrs={
                "placeholder": _("Parcel number"),
                "title": _("Search for parcel number"),
                "class": "form-control",
            }
        ),
    )

    class Meta:
        abstract = True

    def _filter_parcel_reference(self, queryset, filter_q) -> QuerySet:
        """ Filters the parcel entries by a given filter_q

        Args:
            queryset (QuerySet): The queryset
            filter_q (Q): The Q-style filter expression

        Returns:

        """
        matching_parcels = Parcel.objects.filter(
            filter_q
        )

        related_geoms = matching_parcels.values(
            "geometries"
        ).distinct()
        queryset = queryset.filter(
            geometry__id__in=related_geoms
        )
        return queryset

    def filter_district(self, queryset, name, value) -> QuerySet:
        """ Filters queryset depending on value for 'Kreis'

        Args:
            queryset ():
            name ():
            value ():

        Returns:

        """
        values = value.split(",")
        q = Q()
        for val in values:
            val = val.strip()
            q |= Q(name__icontains=val) | Q(key__icontains=val)

        matching_districts = District.objects.filter(q).distinct()
        matching_parcels = Parcel.objects.filter(
            district__in=matching_districts
        )
        related_geoms = matching_parcels.values(
            "geometries"
        ).distinct()
        queryset = queryset.filter(
            geometry__id__in=related_geoms
        )
        return queryset

    def filter_gmrkng(self, queryset, name, value) -> QuerySet:
        """ Filters queryset depending on value for 'Gemarkung'

        Args:
            queryset ():
            name ():
            value ():

        Returns:

        """
        values = value.split(",")
        q = Q()
        for val in values:
            val = val.strip()
            q |= Q(parcel_group__name__icontains=val) | Q(parcel_group__key__icontains=val)
        queryset = self._filter_parcel_reference(
            queryset,
            q,
        )
        return queryset

    def filter_parcel(self, queryset, name, value) -> QuerySet:
        """ Filters queryset depending on value for 'Parcel'

        Args:
            queryset ():
            name ():
            value ():

        Returns:

        """
        queryset = self._filter_parcel_reference(
            queryset,
            Q(flr=value),
        )
        return queryset

    def filter_parcel_counter(self, queryset, name, value) -> QuerySet:
        """ Filters queryset depending on value for 'Parcel'

        Args:
            queryset ():
            name ():
            value ():

        Returns:

        """
        queryset = self._filter_parcel_reference(
            queryset,
            Q(flrstck_zhlr=value)
        )
        return queryset

    def filter_parcel_number(self, queryset, name, value) -> QuerySet:
        """ Filters queryset depending on value for 'Parcel'

        Args:
            queryset ():
            name ():
            value ():

        Returns:

        """
        queryset = self._filter_parcel_reference(
            queryset,
            Q(flrstck_nnr=value),
        )
        return queryset
