"""Utils app serializer."""
import pytz
from django.core import exceptions
from rest_framework import serializers

from favorites.models import Favorites
from main.models import Carousel
from translation.models import Language
from utils import models


class EmptySerializer(serializers.Serializer):
    """Empty Serializer"""


class SourceSerializerMixin(serializers.Serializer):
    """Base authorization serializer mixin"""
    source = serializers.ChoiceField(choices=models.PlatformMixin.SOURCES,
                                     default=models.PlatformMixin.WEB,
                                     write_only=True)


class TranslatedField(serializers.CharField):
    """Translated field."""

    def __init__(self, allow_null=True, required=False, read_only=True,
                 **kwargs):
        super().__init__(allow_null=allow_null, required=required,
                         read_only=read_only, **kwargs)


# todo: view validation in more detail
def validate_tjson(value):
    if not isinstance(value, dict):
        raise exceptions.ValidationError(
            'invalid_json',
            code='invalid_json',
            params={'value': value},
        )
    is_lang = Language.objects.filter(locale__in=value.keys()).exists()
    if not is_lang:
        raise exceptions.ValidationError(
            'invalid_translated_keys',
            code='invalid_translated_keys',
            params={'value': value},
        )


class TJSONField(serializers.JSONField):
    """Custom serializer's JSONField for model's TJSONField."""

    validators = [validate_tjson]


class TimeZoneChoiceField(serializers.ChoiceField):
    """Take the timezone object and make it JSON serializable."""

    def __init__(self, choices=None, **kwargs):
        if choices is None:
            choices = pytz.all_timezones
        super().__init__(choices=choices, **kwargs)

    def to_representation(self, value):
        if isinstance(value, str):
            return value
        elif isinstance(value, pytz.tzinfo.BaseTzInfo):
            return value.zone
        return None

    def to_internal_value(self, data):
        return pytz.timezone(data)


class ProjectModelSerializer(serializers.ModelSerializer):
    """Overridden ModelSerializer."""

    serializers.ModelSerializer.serializer_field_mapping[models.TJSONField] = TJSONField


class FavoritesCreateSerializer(serializers.ModelSerializer):
    """Serializer to favorite object."""

    class Meta:
        model = Favorites
        fields = [
            'id',
            'created',
        ]

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

    @property
    def user(self):
        """Get user from request"""
        return self.request.user

    @property
    def slug(self):
        return self.request.parser_context.get('kwargs').get('slug')


class CarouselCreateSerializer(serializers.ModelSerializer):
    """Carousel to favorite object."""

    class Meta:
        model = Carousel
        fields = [
            'id',
        ]

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

    @property
    def pk(self):
        return self.request.parser_context.get('kwargs').get('pk')

    @property
    def slug(self):
        return self.request.parser_context.get('kwargs').get('slug')


class RecursiveFieldSerializer(serializers.Serializer):
    def to_representation(self, value):
        serializer = self.parent.parent.__class__(value, context=self.context)
        return serializer.data


class ImageBaseSerializer(serializers.Serializer):
    """Serializer for returning crop images of model image."""

    id = serializers.IntegerField()
    title = serializers.CharField()
    original_url = serializers.URLField()
    orientation_display = serializers.CharField()
    auto_crop_images = serializers.DictField(allow_null=True)
