#!/usr/bin/env python
# -*- coding: utf-8 -*-

''' (Data)models which describe the structure of data to be saved into database. '''

import os
import uuid

from django.db import models
from django.dispatch import receiver
from django.contrib.auth.models import AbstractUser
from easy_thumbnails.fields import ThumbnailerImageField

# Create your models here.

class Explorer(AbstractUser):
    """
    Custom user model
    Addtional fields wbd
    """

    def __str__(self):
        return self.username

class Voucher(models.Model):
    """
    Vouchers are authorization tokens to allow the registration of new users.
    A voucher has a code, a creation and a deletion date, which are all positional.
    Creation date is being set automatically during voucher creation. 
    """

    code = models.CharField(unique=True, max_length=10)
    created = models.DateTimeField(auto_now_add=True)
    expires = models.DateField()

    def __str__(self):
        return "Voucher " + str(self.pk)

class Place (models.Model):
    """
    Place defines a lost place (location, name, description etc.).
    """

    name = models.CharField(max_length=50)
    submitted_when = models.DateTimeField(auto_now_add=True, null=True)
    submitted_by = models.ForeignKey(
        Explorer,
        on_delete=models.SET_NULL,
        null=True,
        blank=True, 
        related_name='places'
    )
    location = models.CharField(max_length=50)
    latitude = models.FloatField()
    longitude = models.FloatField()
    description = models.TextField()

    # Get center position of all LP-geocoordinates.

    def average_latlon(place_list):
        amount = len(place_list)
        longitude = 0
        latitude = 0
    
        for place in place_list:
            longitude += place.longitude
            latitude += place.latitude
        return (latitude / amount, longitude / amount)

    def __str__(self):
        return self.name

def generate_image_upload_path(instance, filename):
    """
    Callback for generating path for uploaded images.
    """

    return 'places/' + str(uuid.uuid4())+'.'+filename.split('.')[-1]

class PlaceImage (models.Model):
    """
    PlaceImage defines an image file object that points to a file in uploads/.
    Intermediate image sizes are generated as defined in SIZES.
    PlaceImage references a Place to which it belongs.
    """
        
    description = models.TextField(blank=True)
    filename = ThumbnailerImageField(upload_to=generate_image_upload_path)
    place = models.ForeignKey(
        Place,
        on_delete=models.CASCADE,
        related_name='images'
    )
    submitted_by = models.ForeignKey(
        Explorer,
        on_delete=models.SET_NULL,
        null=True,
        blank=True, 
        related_name='images'
    )

    def __str__(self):
        """
        Returning the name of the corresponding place + id 
        of this image as textual represntation of this instance
        """

        return ' '.join([self.place.name, str(self.pk)])

# These two auto-delete files from filesystem when they are unneeded:

@receiver(models.signals.post_delete, sender=PlaceImage)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """
    Deletes file from filesystem
    when corresponding `PlaceImage` object is deleted.
    """
    if instance.filename:
        if os.path.isfile(instance.filename.path):
            os.remove(instance.filename.path)

@receiver(models.signals.pre_save, sender=PlaceImage)
def auto_delete_file_on_change(sender, instance, **kwargs):
    """
    Deletes old file from filesystem
    when corresponding `PlaceImage` object is updated
    with new file.
    """
    if not instance.pk:
        return False

    try:
        old_file = PlaceImage.objects.get(pk=instance.pk).filename
    except PlaceImage.DoesNotExist:
        return False

    new_file = instance.filename
    if not old_file == new_file:
        if os.path.isfile(old_file.path):
            os.remove(old_file.path)
