from django.contrib.gis.db import models


class SoilOrder(models.Model):
    code = models.CharField(unique=True, max_length=1)
    name = models.CharField(unique=True, max_length=50)

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


class SoilVariant(models.Model):
    name = models.CharField(unique=True, max_length=10)

    def __str__(self):
        return self.name


class SoilLayer(models.Model):
    nzsc_class = models.CharField(max_length=4)
    nzsc_group = models.CharField(max_length=2)
    nzsc_order = models.ForeignKey(SoilOrder, on_delete=models.CASCADE)
    shape_leng = models.FloatField()
    geom = models.PolygonField(srid=2193)

    def __str__(self):
        return self.nzsc_class


class EcologicalRegion(models.Model):
    name = models.CharField(unique=True, max_length=50)

    def __str__(self):
        return self.name


class EcologicalDistrictLayer(models.Model):
    ecological = models.CharField(max_length=5)
    ecologic_1 = models.CharField(max_length=50)
    ecologic_2 = models.ForeignKey(EcologicalRegion, on_delete=models.CASCADE)
    shape_leng = models.FloatField()
    shape_area = models.FloatField()
    geom = models.PolygonField(srid=2193)

    def __str__(self):
        return f"{self.ecologic_1} ({self.ecologic_2})"


class ChristchurchRegion(models.Model):
    objectid = models.IntegerField()
    name = models.CharField(max_length=25)
    geom = models.MultiPolygonField(srid=2193)


class ToleranceLevel(models.Model):
    level = models.CharField(max_length=1)

    def __str__(self):
        return self.level


class Habitat(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name


class HabitatImage(models.Model):
    habitat = models.ForeignKey(
        Habitat, related_name='images', on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    image_filename = models.CharField(max_length=50, default='-')

    def __str__(self):
        return self.name


class Zone(models.Model):
    name = models.CharField(max_length=50)
    variant = models.CharField(null=True, blank=True, max_length=50)
    refined_variant = models.CharField(null=True, blank=True, max_length=100)
    habitat = models.ForeignKey(
        Habitat, blank=True, null=True, on_delete=models.CASCADE,  related_name='zones')
    redirect_habitat = models.ForeignKey(
        Habitat, blank=True, null=True, on_delete=models.CASCADE,  related_name='zone_redirects')
    related_svg_segment = models.CharField(null=True, blank=True, max_length=20)
    ignore_soil_order_filter = models.BooleanField(default=False)
    ignore_location_filter = models.BooleanField(default=False)
    tooltipText = models.CharField(null=True, blank=True, max_length=500)

    @property
    def tooltip_display_text(self):
        return self.tooltipText if self.tooltipText is not None else str(self)

    def __str__(self):
        refined_variant_str = f", {self.refined_variant}" if self.refined_variant is not None else ""
        variant_str = f"({self.variant}{refined_variant_str})" if self.variant is not None else ""
        return f"{self.name} {variant_str}"

    class Meta:
        ordering = ['name', 'variant', 'refined_variant', 'id']


class Plant(models.Model):
    name = models.CharField(unique=True, max_length=50)
    commonname = models.CharField(null=True, blank=True, max_length=200)
    maxheight = models.CharField(max_length=20)
    spacing = models.FloatField()
    synonym = models.CharField(null=True, blank=True, max_length=200)
    water_tolerance = models.ForeignKey(
        ToleranceLevel, related_name='water_tolerance', on_delete=models.CASCADE)
    drought_tolerance = models.ForeignKey(
        ToleranceLevel, related_name='drought_tolerance', on_delete=models.CASCADE)
    frost_tolerance = models.ForeignKey(
        ToleranceLevel, related_name='frost_tolerance', on_delete=models.CASCADE)
    salinity_tolerance = models.ForeignKey(
        ToleranceLevel, related_name='salinity_tolerance', on_delete=models.CASCADE)
    purpose = models.TextField(null=True, blank=True)
    stage = models.PositiveIntegerField()
    growth_form = models.CharField(null=True, blank=True, max_length=50)
    ecological_regions = models.ManyToManyField(EcologicalRegion)
    soil_order = models.ManyToManyField(SoilOrder)
    soil_variants = models.ManyToManyField(SoilVariant)
    zones = models.ManyToManyField(Zone)

    @property
    def forest_position(self):
        return self.zones.all().filter(name="BUSH PROFILE POSITION", variant__in={"Core", "Border", "Skin", "Epiphytes"}).values('variant')

    @property
    def display_name(self):
        common_name_str = f' / {str(self.commonname)}' if self.commonname is not None else ''
        synonym_str = f' / {str(self.synonym)}' if self.synonym is not None else ''
        return f"{self.name}{common_name_str}{synonym_str}"

    @property
    def display_growth_form(self):
        growth_form_str = f'{str(self.growth_form)} / ' if self.growth_form is not None else ''
        forest_position_values_str = ', '.join([position['variant'][0] for position in self.forest_position])
        forest_position_str = f' / {forest_position_values_str}' if len(self.forest_position) != 0 else ''
        return f"{growth_form_str}{self.maxheight} / {self.spacing}{forest_position_str}"

    @property
    def moisture_preferences(self):
        return ', '.join([variant.name for variant in self.soil_variants.all()])

    @property
    def plant_tolerances(self):
        return f"{self.water_tolerance.level} / {self.drought_tolerance.level} / {self.frost_tolerance.level} / {self.salinity_tolerance.level}"

    @property
    def ecosystem_services(self):
        return f"{str(self.purpose) or ''}"

    @property
    def carbon_sequestration(self):
        return ""

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['stage', 'name', 'commonname', 'synonym']
