from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.dispatch import receiver
from django.contrib.auth import get_user_model

from model_utils import FieldTracker

from . import tasks

from colorfield.fields import ColorField

from datetime import date

import os
import uuid


UserModel = get_user_model()


class PhotoTag(models.Model):
    name = models.CharField(unique=True, null=False, blank=False, max_length=100)
    color = ColorField(default='#FFE5B4')

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('name',)


class PhotoGroup(models.Model):
    name = models.CharField(unique=False, null=False, max_length=200)
    date = models.DateField(null=True)
    parent = models.ForeignKey('self', blank=True, null=True, on_delete=models.SET_NULL)

    owner = models.ForeignKey(
        UserModel,
        on_delete=models.CASCADE,
        related_name='photogroups',
    )

    def __str__(self):
        return self.name


def get_default_photogroup():
    return PhotoGroup.objects.get_or_create(
                name="Unsortiert",
                date=None,
            )

def get_original_photo_path(instance, filename):
    _, ext = os.path.splitext(filename)
    return 'original_images/%s%s' % (str(uuid.uuid4()), ext)

def get_cropped_photo_path(instance, filename):
    _, ext = os.path.splitext(filename)
    return 'cropped_images/%s%s' % (str(uuid.uuid4()), ext)


class Photo(models.Model):
    legacy_id = models.IntegerField(unique=True, blank=True, null=True)
    original_image = models.ImageField(upload_to=get_original_photo_path, null=False, blank=False)
    cropped_image = models.ImageField(upload_to=get_cropped_photo_path, null=True, blank=True)
    bbox_coords = ArrayField(
            ArrayField(
                models.IntegerField(unique=False, blank=False, null=True, default=None),
                size=2
            ),
            blank=True,
            null=True,
            default=None,
            size=4,
    )
    rotate = models.FloatField(blank=True, null=True)
    intersections = ArrayField(
            ArrayField(
                models.IntegerField(unique=False, blank=False, null=True, default=None),
                size=2
            ),
            blank=True,
            null=True,
            default=None
    )
    group = models.ForeignKey(
            PhotoGroup,
            null=False,
            blank=True,
            on_delete=models.SET_DEFAULT,
            default=get_default_photogroup
    )
    ocr_text = models.CharField(max_length=200, null=True, blank=True)
    tag = models.ForeignKey(
        PhotoTag,
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        default=None,
    )

    owner = models.ForeignKey(
        UserModel,
        on_delete=models.CASCADE,
        related_name='photos',
    )

    tracker = FieldTracker()

    def __str__(self):
        return "Photo #" + str(self.id)


@receiver(models.signals.post_delete, sender=Photo)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    if instance.original_image:
        instance.original_image.delete(save=False)

    if instance.cropped_image:
        instance.cropped_image.delete(save=False)


@receiver(models.signals.pre_save, sender=Photo)
def auto_delete_file_on_change(sender, instance, **kwargs):
    if not instance.pk:
        return False

    try:
        photo = Photo.objects.get(pk=instance.pk)
    except Photo.DoesNotExist:
        return False

    # check original image for change
    new_file = instance.original_image
    old_file = photo.original_image
    if not old_file == new_file:
        photo.original_image.delete(save=False)

    # check cropped image for change
    new_file = instance.cropped_image
    old_file = photo.cropped_image
    if not old_file == new_file:
        photo.cropped_image.delete(save=False)


@receiver(models.signals.post_save, sender=Photo)
def max_resize_images(sender, instance, **kwargs):
    MAX_IMAGE_WIDTH = 800

    tracker = instance.tracker

    original_image_s3_path = instance.original_image.name
    if original_image_s3_path and tracker.has_changed('original_image'):
        tasks.max_resize_image_chain(original_image_s3_path, MAX_IMAGE_WIDTH)

    cropped_image_s3_path = instance.cropped_image.name
    if cropped_image_s3_path and tracker.has_changed('cropped_image'):
        tasks.max_resize_image_chain(cropped_image_s3_path, MAX_IMAGE_WIDTH)


def get_empty_photolog_default():
    return []

def get_photolog_pdf_path(instance, filename):
    return "photolog_pdf/%s.pdf" % str(uuid.uuid4())

class PhotoLog(models.Model):
    title = models.CharField(null=False, blank=False, max_length=5000)
    date = models.DateField(auto_now=False, default=date.today)
    render_date = models.BooleanField(null=False, blank=True, default=True)
    start_slide_image = models.IntegerField(null=True, blank=True, default=3)
    slides = ArrayField(
        ArrayField(
            models.IntegerField(blank=False, null=True),
            null=True,
            blank=True,
            size=3
        ),
        null=False,
        blank=True,
        default=get_empty_photolog_default
    )
    pdf = models.FileField(upload_to=get_photolog_pdf_path, null=True, blank=True)

    def __str__(self):
        return self.title


class PhotoLogTemplate(models.Model):
    title = models.CharField(null=False, blank=False, max_length=5000)
    date = models.DateField(auto_now=False, default=date.today)
    render_date = models.BooleanField(null=False, blank=True, default=True)
    start_slide_image = models.IntegerField(null=True, blank=True, default=3)
    slides = models.JSONField(
            null=False,
            blank=False,
            default=list,
    )

    def __str__(self):
        return self.title


@receiver(models.signals.post_delete, sender=PhotoLog)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    if instance.pdf:
        instance.pdf.delete(save=False)
