"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 16.12.21

"""
from django.db import models

from konova.models import UuidModel


class AdministrativeSpatialReference(models.Model):
    key = models.CharField(
        max_length=255,
        help_text="Represents Kreisschlüssel",
        null=True,
        blank=True
    )
    name = models.CharField(
        max_length=1000,
        help_text="Kreis",
        null=True,
        blank=True,
    )

    class Meta:
        abstract = True

    def __str__(self):
        return f"{self.name} ({self.key})"

    @property
    def table_str(self):
        return f"{self.name} ({self.key})"


class District(UuidModel, AdministrativeSpatialReference):
    """ The model District refers to "Kreis"

    """

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=[
                    "key",
                    "name",
                ],
                name="Unique district constraint"
            )
        ]


class Municipal(UuidModel, AdministrativeSpatialReference):
    """ The model Municipal refers to "Gemeinde"

    """
    district = models.ForeignKey(
        District,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=[
                    "key",
                    "name",
                    "district",
                ],
                name="Unique municipal constraint"
            )
        ]


class ParcelGroup(UuidModel, AdministrativeSpatialReference):
    """ The model ParcelGroup refers to "Gemarkung", which is defined as a loose group of parcels

    """
    municipal = models.ForeignKey(
        Municipal,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=[
                    "key",
                    "name",
                    "municipal",
                ],
                name="Unique parcel group constraint"
            )
        ]


class Parcel(UuidModel):
    """ The Parcel model holds administrative data on covered properties.

    Due to the unique but relevant naming of the administrative data, we have to use these namings as field
    names in german. Any try to translate them to English result in strange or insufficient translations.

    All fields have to be CharFields as well, since there are e.g. Flurstücksnummer holding e.g. '123____' which
    can not be realized using numerical fields.

    To avoid conflicts due to german Umlaute, the field names are shortened and vocals are dropped.

    """
    geometries = models.ManyToManyField("konova.Geometry", blank=True, related_name="parcels", through='ParcelIntersection')
    district = models.ForeignKey("konova.District", on_delete=models.SET_NULL, null=True, blank=True, related_name="parcels")
    municipal = models.ForeignKey("konova.Municipal", on_delete=models.SET_NULL, null=True, blank=True, related_name="parcels")
    parcel_group = models.ForeignKey(
        "konova.ParcelGroup",
        on_delete=models.SET_NULL,
        help_text="Gemarkung",
        null=True,
        blank=True,
        related_name="parcels"
    )
    flr = models.IntegerField(
        help_text="Flur",
        null=True,
        blank=True,
    )
    flrstck_nnr = models.IntegerField(
        help_text="Flurstücksnenner",
        null=True,
        blank=True,
    )
    flrstck_zhlr = models.IntegerField(
        help_text="Flurstückszähler",
        null=True,
        blank=True,
    )
    updated_on = models.DateTimeField(auto_now_add=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=[
                    "district",
                    "municipal",
                    "parcel_group",
                    "flr",
                    "flrstck_nnr",
                    "flrstck_zhlr",
                ],
                name="Unique parcel constraint"
            )
        ]

    def __str__(self):
        return f"{self.parcel_group} | {self.flr} | {self.flrstck_zhlr} | {self.flrstck_nnr}"


class ParcelIntersection(UuidModel):
    """ ParcelIntersection is an intermediary model, which is used to configure the
    M2M relation between Parcel and Geometry.

    Based on uuids, we will not have (practically) any problems on outrunning primary keys
    and extending the model with calculated_on timestamp, we can 'hide' entries while they
    are being recalculated and keep track on the last time they have been calculated this
    way.

    Please note: The calculated_on describes when the relation between the Parcel and the Geometry
    has been established. The updated_on field of Parcel describes when this Parcel has been
    changed the last time.

    """
    parcel = models.ForeignKey(Parcel, on_delete=models.CASCADE)
    geometry = models.ForeignKey("konova.Geometry", on_delete=models.CASCADE)
    calculated_on = models.DateTimeField(auto_now_add=True, null=True, blank=True)
