from rest_framework import serializers, pagination

from ..constants import CATEGORY
from ..utils import expand

from .base import DynamicFieldsSerializer
from .icon import IconSerializer
from .lang_pair import LangPairSerializer
from .owner import OwnerSerializer
from .service import ServiceSerializer


class AchievementSerializer(DynamicFieldsSerializer):
    domain_object_class = 'Achievement'

    # TODO: We can avoid that trash by using partial=True, can't we?
    id = serializers.IntegerField(required=False)
    category = serializers.ChoiceField(CATEGORY, required=False)
    created_at = serializers.DateTimeField(read_only=True)
    description = LangPairSerializer(required=False)
    description_html = LangPairSerializer(required=False)
    description_short = LangPairSerializer(required=False)
    title = LangPairSerializer(required=False)
    owner_group = OwnerSerializer(required=False)
    service = ServiceSerializer(required=False)
    icon_big = IconSerializer(read_only=True)
    icon_small = IconSerializer(read_only=True)
    is_active = serializers.BooleanField(required=False)
    is_counter = serializers.BooleanField(read_only=True)

    roles = serializers.Field(source='_roles')

    def restore_fields(self, data, files):
        data = expand(data)
        return super(AchievementSerializer, self).restore_fields(data, files)

    def restore_object(self, attrs, instance=None):
        if not instance and 'id' in attrs:
            return (
                self.get_domain_object_class()
                    .objects(self.user, self.role_registry)
                    .filter(owner_group__members__id=self.user.id)
                    .get(pk=attrs['id'])
            )

        return super(AchievementSerializer, self).restore_object(
            attrs, instance)


class PaginatedAchievementSerializer(pagination.BasePaginationSerializer):
    results_field = 'objects'
    total = serializers.Field(source='paginator.count')
    limit = serializers.Field(source='paginator.per_page')
    pages = serializers.Field(source='paginator.num_pages')
    page = serializers.Field(source='number')

    def __init__(self, *args, **kwargs):
        """
        Override init to add in the object serializer field on-the-fly.
        """
        fields = kwargs.pop('fields', None)
        super(PaginatedAchievementSerializer, self).__init__(*args, **kwargs)
        results_field = self.results_field
        object_serializer = self.opts.object_serializer_class

        if 'context' in kwargs:
            context_kwarg = {'context': kwargs['context']}
        else:
            context_kwarg = {}

        if fields:
            context_kwarg['fields'] = fields

        self.fields[results_field] = object_serializer(source='object_list',
                                                       **context_kwarg)

    # noinspection PyClassicStyleClass
    class Meta:
        object_serializer_class = AchievementSerializer
