""" This module holds the serializers of the ``brainstormers`` app. """

from rest_framework import serializers
from rest_framework.exceptions import ParseError

from mtp.apps.brainstormers.constants import GROUP, MODULE, PREVIEW
from mtp.apps.brainstormers.models import (
    DEFAULT_GROUP_ATTRIBUTES,
    Brainstormer,
    BrainstormerActivity,
    BrainstormerProposition,
    BrainstormerPropositionGroup,
    BrainstormerTemplate
)

from mtp.apps.likes.api.serializers import LikeableSerializer
from mtp.apps.trainings.models import TrainingSession


class BrainstormerActivitySerializer(serializers.ModelSerializer):
    """
    Serializer for ``brainstormers.BrainstormerActivity`` objects.
    """

    class Meta:
        model = BrainstormerActivity
        fields = ('id', 'name', 'preview', 'image',
                  'hash_preview', 'hash_image', 'trainings')


class BrainstormerTemplateSerializer(serializers.ModelSerializer):
    """
    Serializer for ``brainstormers.BrainstormerTemplate`` objects.
    """

    class Meta:
        model = BrainstormerTemplate
        fields = ('id', 'title', 'activity', 'training')


class BrainstormerPropositionSerializer(LikeableSerializer, serializers.ModelSerializer):
    """Serializer for ``brainstormers.BrainstormerProposition`` objects."""

    group = serializers.PrimaryKeyRelatedField(
        queryset=BrainstormerPropositionGroup.objects.filter(is_deleted=False),
        required=False
    )
    modified = serializers.DateTimeField(
        read_only=True
    )
    created = serializers.DateTimeField(
        read_only=True
    )

    class Meta(LikeableSerializer.Meta):
        model = BrainstormerProposition
        fields = (
            'id',
            'text',
            'group',
            'user',
            'created',
            'modified',
        ) + LikeableSerializer.Meta.fields

    def create(self, validated_data):
        try:
            group = validated_data.pop('group')
        except KeyError:

            # No group was given in parameters, so we get or create a default
            # one in the brainstormer specified in the url.
            brainstormer_id = self.context.get('view').kwargs.get('parent_lookup_group'
                                                                  '__brainstormer')
            brainstormer = Brainstormer.objects.get(id=brainstormer_id)
            group, __ = BrainstormerPropositionGroup.objects.get_or_create(
                brainstormer=brainstormer, **DEFAULT_GROUP_ATTRIBUTES)

        except Brainstormer.DoesNotExist:
            raise ParseError("brainstormer_id incorrect : object does not exist")

        return BrainstormerProposition.objects.create(group=group, **validated_data)


class BrainstormerSimplePropositionGroupSerializer(serializers.ModelSerializer):
    """Serializer for ``brainstormers.BrainstormerPropositionGroup`` model.

    This serializer is "simple": it does not include the nested relationships.

    """

    order = serializers.IntegerField(source='sort_order', required=False)  # For iOS compatibility

    class Meta:
        model = BrainstormerPropositionGroup
        fields = ('id', 'name', 'color', 'order',)




class BrainstormerPropositionGroupSerializer(serializers.ModelSerializer):
    """
    Serializer for ``brainstormers.BrainstormerPropositionGroup`` objects.

    """

    brainstormer = serializers.PrimaryKeyRelatedField(read_only=True)
    propositions = BrainstormerPropositionSerializer(many=True, read_only=True)
    order = serializers.IntegerField(source='sort_order', required=False)  # For iOS compatibility
    x = serializers.DecimalField(  # pylint: disable=invalid-name
        max_digits=6,
        decimal_places=2,
        source='coord_x',  # For iOS compatibility
        required=False
    )
    y = serializers.DecimalField(  # pylint: disable=invalid-name
        max_digits=6,
        decimal_places=2,
        source='coord_y',  # For iOS compatibility
        required=False
    )

    class Meta:
        model = BrainstormerPropositionGroup
        fields = ('id', 'name', 'brainstormer', 'color',
                  'x', 'y', 'order', 'propositions')

    def create(self, validated_data):
        brainstormer_id = self.context.get('view').kwargs.get('parent_lookup_brainstormer')

        try:
            brainstormer = Brainstormer.objects.get(id=brainstormer_id)
        except Brainstormer.DoesNotExist:
            raise ParseError("brainstormer_id incorrect : object does not exist")

        return BrainstormerPropositionGroup.objects.create(
            brainstormer=brainstormer, **validated_data
        )


class BrainstormerSerializer(serializers.ModelSerializer):
    """
    Serializer for ``brainstormers.Brainstormer`` objects.
    """

    preview = serializers.SerializerMethodField(read_only=True)
    module = serializers.SerializerMethodField(read_only=True)
    groups = serializers.SerializerMethodField(read_only=True)
    order = serializers.IntegerField(source="sort_order", required=False)  # For iOS compatibility
    proposals = BrainstormerPropositionSerializer(
        source="get_propositions", many=True, read_only=True)
    proposal_groups = BrainstormerPropositionGroupSerializer(
        source="groups", many=True, read_only=True
    )
    training_session = serializers.PrimaryKeyRelatedField(
        source="session",
        queryset=TrainingSession.objects.non_deleted()
    )
    title = serializers.CharField(source="name")

    class Meta:
        model = Brainstormer
        fields = ('id', 'title', 'training_session',
                  'preview', 'module', 'groups', 'order', 'activity',
                  'proposals', 'proposal_groups', 'anonymous')

    @staticmethod
    def get_preview(instance):  # pylint: disable=unused-argument
        """Return the PREVIEW constant value.

        For the parameters, see ``rest_framework.serializers.ModelSerializer``"""

        return PREVIEW

    @staticmethod
    def get_module(instance):  # pylint: disable=unused-argument
        """Return the MODULE constant value.

        For the parameters, see ``rest_framework.serializers.ModelSerializer``"""

        return MODULE

    @staticmethod
    def get_groups(instance):  # pylint: disable=unused-argument
        """Return the GROUP constant value.

        For the parameters, see ``rest_framework.serializers.ModelSerializer``"""

        return GROUP
