from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.files.base import ContentFile
from rest_framework import serializers
from sorl.thumbnail import get_thumbnail
from sorl.thumbnail.parsers import parse_crop, ThumbnailParseError
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from . import models


class ImageSerializer(serializers.ModelSerializer):
    """Serializer for model Image."""
    # REQUEST
    file = serializers.ImageField(source='image',
                                  write_only=True)

    # RESPONSE
    url = serializers.ImageField(source='image',
                                 read_only=True)
    orientation_display = serializers.CharField(source='get_orientation_display',
                                                read_only=True)

    class Meta:
        """Meta class"""
        model = models.Image
        fields = [
            'id',
            'file',
            'url',
            'orientation',
            'orientation_display',
            'title',
        ]
        extra_kwargs = {
            'orientation': {'write_only': True}
        }

    def validate(self, attrs):
        """Overridden validate method."""
        image = attrs.get('image')

        if image and image.size >= settings.FILE_UPLOAD_MAX_MEMORY_SIZE:
            raise serializers.ValidationError({'detail': _('File size too large: %s bytes') % image.size})

        return attrs


class CropImageSerializer(ImageSerializer):
    """Serializers for image crops."""

    width = serializers.IntegerField(write_only=True, required=False)
    height = serializers.IntegerField(write_only=True, required=False)
    crop = serializers.CharField(write_only=True,
                                 required=False,
                                 default='center')
    quality = serializers.IntegerField(write_only=True, required=False,
                                       default=settings.THUMBNAIL_QUALITY,
                                       validators=[
                                           MinValueValidator(1),
                                           MaxValueValidator(100)])
    cropped_image = serializers.DictField(read_only=True, allow_null=True)

    class Meta(ImageSerializer.Meta):
        """Meta class."""
        fields = [
            'id',
            'url',
            'orientation_display',
            'width',
            'height',
            'crop',
            'quality',
            'cropped_image',
        ]

    def validate(self, attrs):
        """Overridden validate method."""
        file = self._image.image
        crop_width = attrs.get('width')
        crop_height = attrs.get('height')
        crop = attrs.get('crop')

        if (crop_height and crop_width) and (crop and crop != 'smart'):
            xy_image = (file.width, file.width)
            xy_window = (crop_width, crop_height)
            try:
                parse_crop(crop, xy_image, xy_window)
                attrs['image'] = file
            except ThumbnailParseError:
                raise serializers.ValidationError({'margin': _('Unrecognized crop option: %s') % crop})
        return attrs

    def create(self, validated_data):
        """Overridden create method."""
        width = validated_data.pop('width', None)
        height = validated_data.pop('height', None)
        quality = validated_data.pop('quality')
        crop = validated_data.pop('crop')

        crop_params = {
            'geometry': f'{width}x{height}',
            'quality': quality,
            'crop': crop,
        }
        cropped_image = self._image.get_cropped_image(**crop_params)
        image = self._image
        image.pk = None
        crop_params['geometry_string'] = crop_params.pop('geometry')
        resized = get_thumbnail(self._image.image, **crop_params)
        image.image.save(resized.name, ContentFile(resized.read()), True)
        image.save()

        if image and width and height:
            setattr(image,
                    'cropped_image',
                    cropped_image)
        return image

    @property
    def view(self):
        return self.context.get('view')

    @property
    def lookup_field(self):
        lookup_field = 'pk'

        if lookup_field in self.view.kwargs:
            return self.view.kwargs.get(lookup_field)

    @property
    def _image(self):
        """Return image from url_kwargs."""
        qs = models.Image.objects.filter(id=self.lookup_field)
        if qs.exists():
            return qs.first()
        raise serializers.ValidationError({'detail': _('Image not found.')})
