from rest_framework import serializers

from collection import models
from collection.serializers.common import CollectionBaseSerializer
from establishment.models import Establishment
from location.models import Country
from location.serializers import CountrySimpleSerializer
from product.models import Product
from utils.exceptions import (
    BindingObjectNotFound, ObjectAlreadyAdded,
    RemovedBindingObjectNotFound,
)


class CollectionBackOfficeSerializer(CollectionBaseSerializer):
    """Collection back serializer."""
    country_id = serializers.PrimaryKeyRelatedField(
        source='country', write_only=True,
        queryset=Country.objects.all())
    collection_type_display = serializers.CharField(
        source='get_collection_type_display', read_only=True)
    country = CountrySimpleSerializer(read_only=True)
    count_related_objects = serializers.IntegerField(read_only=True)
    related_object_names = serializers.ListField(read_only=True)

    class Meta:
        model = models.Collection
        fields = CollectionBaseSerializer.Meta.fields + [
            'id',
            'name',
            'collection_type',
            'collection_type_display',
            'is_publish',
            'on_top',
            'country',
            'country_id',
            # 'block_size',
            'description',
            'slug',
            # 'start',
            # 'end',
            'count_related_objects',
            'related_object_names',
            'rank',
        ]
        extra_kwargs = {
            'slug': {'read_only': True},
        }


class CollectionBindObjectSerializer(serializers.Serializer):
    """Serializer for binding collection and objects"""

    ESTABLISHMENT = 'establishment'
    PRODUCT = 'product'

    TYPE_CHOICES = (
        (ESTABLISHMENT, 'Establishment'),
        (PRODUCT, 'Product'),
    )

    type = serializers.ChoiceField(TYPE_CHOICES)
    object_id = serializers.IntegerField()

    def validate(self, attrs):
        view = self.context.get('view')
        request = self.context.get('request')

        obj_type = attrs.get('type')
        obj_id = attrs.get('object_id')

        collection = view.get_object()
        attrs['collection'] = collection

        if obj_type == self.ESTABLISHMENT:
            establishment = Establishment.objects.filter(pk=obj_id). \
                first()
            if not establishment:
                raise BindingObjectNotFound()
            if request.method == 'POST' and collection.establishments. \
                    filter(pk=establishment.pk).exists():
                raise ObjectAlreadyAdded()
            if request.method == 'DELETE' and not collection. \
                    establishments.filter(pk=establishment.pk). \
                    exists():
                raise RemovedBindingObjectNotFound()
            attrs['related_object'] = establishment
        elif obj_type == self.PRODUCT:
            product = Product.objects.filter(pk=obj_id).first()
            if not product:
                raise BindingObjectNotFound()
            if request.method == 'POST' and collection.products. \
                    filter(pk=product.pk).exists():
                raise ObjectAlreadyAdded()
            if request.method == 'DELETE' and not collection.products. \
                    filter(pk=product.pk).exists():
                raise RemovedBindingObjectNotFound()
            attrs['related_object'] = product
        return attrs
