
from datetime import date

from rest_framework import serializers
from fb.feedback.models import Feedback, FeedbackGroup, FeedbackRequest, BlackList
from fb.staff import serializers as staff
from fb.quizz.serializers import PersonAnswerSerializer
from fb.quizz.models import PersonAnswer


__all__ = ['FeedbackSerializer']


class FeedbackGroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = FeedbackGroup
        fields = ('id', 'person')


class BlackListSerializer(serializers.ModelSerializer):
    class Meta:
        model = BlackList
        fields = ('id', 'person')


class FeedbackSerializer(serializers.ModelSerializer):

    feedback_group = FeedbackGroupSerializer(many=True, write_only=True,
                                             allow_add_remove=True)

    blacklist = BlackListSerializer(
        many=True, write_only=True, allow_add_remove=True,
        default=[],
    )
    #persons = staff.PersonSerializer(many=True, required=False)
    persons_staff = staff.InflatedPersonSerializer(many=True, source='persons',
                                                   read_only=True)

    blacklisted_persons_staff = staff.PersonSerializer(
        many=True, source='blacklisted_persons', read_only=True,
    )

    reporter_staff = staff.PersonSerializer(source='reporter', read_only=True)

    quizz_answers = PersonAnswerSerializer(source='personanswer_set', many=True)

    class Meta:
        model = Feedback
        read_only_fields = (
            'id', 'reporter', 'create_time',
            'change_time', 'create_time',
            'is_changed',
        )

    def from_native(self, data, files=None):
        if data and 'persons' in data:
            data['feedback_group'] = [{'person': p} for p in data['persons']]

        if data and 'blacklisted_persons' in data:
            data['blacklist'] = [{'person': p} for p in data['blacklisted_persons']]
        return super(FeedbackSerializer, self).from_native(data, files)

    def to_native(self, instance):
        ret = super(FeedbackSerializer, self).to_native(instance)
        ret['quizz_answers'] = []
        if hasattr(self, 'context') and 'requester' in self.context:
            requester = self.context['requester']
            for answer in instance.personanswer_set.all():
                show_quizzes = (
                    requester == answer.on_whom or
                    requester.is_head_of(answer.on_whom) or
                    requester.has_read_role(answer.on_whom)
                )
                if show_quizzes:
                    ret['quizz_answers'].append(
                        PersonAnswerSerializer(instance=answer).data
                    )
        return ret


class FeedbackForReviewSerializer(serializers.ModelSerializer):

    reporter_staff = staff.PersonSerializer(source='reporter', read_only=True)

    class Meta:
        model = Feedback
        read_only_fields = (
            'id',
            'reporter',
            'change_time',
            'create_time',
            'is_changed',
        )


class PersonSerializer(serializers.Serializer):
    id = serializers.IntegerField()

class PersonSerializerWithRaiting(staff.PersonSerializer):

    def to_native(self, instance):
        ret = super(PersonSerializerWithRaiting, self).to_native(instance)
        positive_messages = instance.feedbacks.all().values_list('positive_message', flat=True)
        negative_messages = instance.feedbacks.all().values_list('negative_message', flat=True)
        messages_processor = lambda message: len(message.split(' '))
        positive_messages = map(messages_processor, positive_messages)
        negative_messages = map(messages_processor, negative_messages)
        #get messages with count of words > 5
        messages_filter = lambda words_count: words_count > 5
        positive_messages = filter(messages_filter, positive_messages)
        negative_messages = filter(messages_filter, negative_messages)
        ret['positive_messages'] = len(positive_messages)
        ret['negative_messages'] = len(negative_messages)
        return ret


class SuggestFeedbackSerializer(serializers.Serializer):
    suggested_persons = PersonSerializer(many=True, blank=False, required=True)
    suggest_to = PersonSerializer(many=True, blank=False, required=True)
    reason = serializers.CharField(blank=True, required=False)
    is_group_request = serializers.BooleanField(default=True)
    deadline = serializers.DateField(default=None, required=False)

    @staticmethod
    def _pack_attribute(data, attr_name):
        if data:
            data[attr_name] = [{'id': i} for i in data.get(attr_name, [])]

    def from_native(self, data, files=None):
        if data:
            self._pack_attribute(data, 'suggested_persons')
            self._pack_attribute(data, 'suggest_to')
        return super(SuggestFeedbackSerializer, self).from_native(data, files)

    def validate_deadline(self, attrs, source):
        value = attrs.get(source)
        if value and value < date.today():
            raise serializers.ValidationError("Deadline shouldn't be in past")
        return attrs


class RequestFeedbackSerializer(serializers.ModelSerializer):

    suggested_persons = staff.PersonSerializer(many=True)
    suggest_to = staff.InflatedPersonSerializer()
    reporter = staff.PersonSerializer()

    class Meta:
        model = FeedbackRequest


class SubmitRequestSerializer(serializers.ModelSerializer):

    class Meta:
        model = FeedbackRequest
        fields = ('is_submitted',)
