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

import random

from rest_framework import serializers

from mtp.apps.accounts.constants import INTERNAL_GROUP_TRAINEE, INTERNAL_GROUP_TRAINER

from .models import (
    Workshop,
    WorkshopStep,
    WorkshopStepQuestion,
    WorkshopStepImage,
    WorkshopStepQuestionAnswer,
)


class CompatibilityWorkshopStepQuestionAnswerSerializer(serializers.ModelSerializer):
    """Serializer for the ``mtp.apps.workshop.models.WorkshopStepQuestionAnswer`` model."""

    good = serializers.SerializerMethodField()
    order = serializers.SerializerMethodField()

    class Meta:
        model = WorkshopStepQuestionAnswer
        fields = [
            'id',
            'label',
            'good',
            'points',
            'order'
        ]

    def get_good(self, instance):
        return instance.is_correct

    def get_order(self, instance):
        return instance.sort_order


class CompatibilityWorkshopStepQuestionSerializer(serializers.ModelSerializer):
    """Serializer for the ``mtp.apps.workshop.models.WorkshopStepQuestion`` model."""

    label = serializers.SerializerMethodField()
    type = serializers.SerializerMethodField()
    options = serializers.SerializerMethodField()
    order = serializers.SerializerMethodField()
    answers = serializers.SerializerMethodField()

    class Meta:
        model = WorkshopStepQuestion
        fields = [
            'id',
            'label',
            'description',
            'is_multiple_choices',
            'type',
            'options',
            'order',
            'answers',
        ]

    def get_label(self, instance):
        return instance.title

    def get_type(self, instance):  # pylint: disable=unused-argument
        return 'quizz'

    def get_options(self, instance):  # pylint: disable=unused-argument
        return []

    def get_order(self, instance):
        return instance.sort_order

    def get_answers(self, instance):
        answers_qs = WorkshopStepQuestionAnswer.objects.filter(
            question=instance).order_by('sort_order').non_deleted()
        answers = CompatibilityWorkshopStepQuestionAnswerSerializer(
            answers_qs, many=True, read_only=True)

        answers_list = answers.data

        if (instance.workshop.is_questions_answers_order_random
                or instance.is_answers_order_random):
            random.shuffle(answers_list)

        return answers_list


class CompatibilityWorkshopStepImageSerializer(serializers.ModelSerializer):
    """Serializer for the ``mtp.apps.workshop.models.WorkshopStepImage`` model."""

    label = serializers.CharField(source='title')
    type = serializers.SerializerMethodField()
    options = serializers.SerializerMethodField()
    order = serializers.IntegerField(source='sort_order')
    description = serializers.ImageField(source='image')
    answers = serializers.SerializerMethodField()

    class Meta:
        model = WorkshopStepImage
        fields = [
            'id',
            'label',
            'description',
            'type',
            'options',
            'order',
            'answers',
        ]

    @staticmethod
    def get_type(instance):  # pylint: disable=unused-argument
        return 'img'

    @staticmethod
    def get_options(instance):  # pylint: disable=unused-argument
        return []

    @staticmethod
    def get_answers(instance):  # pylint: disable=unused-argument
        return []


class CompatibilityWorkshopSerializer(serializers.ModelSerializer):
    """Serializer for the ``mtp.apps.workshop.models.Workshop`` model."""

    title = serializers.SerializerMethodField()
    type = serializers.SerializerMethodField()
    order = serializers.SerializerMethodField()
    groups = serializers.SerializerMethodField()
    has_score = serializers.SerializerMethodField()
    answers_required = serializers.SerializerMethodField()
    module = serializers.SerializerMethodField()
    preview = serializers.SerializerMethodField()
    questions = serializers.SerializerMethodField()

    class Meta:
        model = Workshop
        fields = [
            'id',
            'original_version',
            'title',
            'type',
            'order',
            'groups',
            'has_score',
            'needs_approval',
            'answers_required',
            'is_assessing',
            'module',
            'preview',
            'questions'
        ]

    def get_title(self, instance):
        return instance.name

    def get_type(self, instance):
        return 'livevoting' if instance.is_broadcastable else 'workshop'

    def get_order(self, instance):
        return instance.sort_order

    def get_groups(self, instance):
        """Get the allowed user's groups for this workshop

        A "broadcastable" workshop can only be launched by the trainers.

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

        """

        if instance.is_broadcastable:
            return [INTERNAL_GROUP_TRAINER]
        else:
            return [INTERNAL_GROUP_TRAINER, INTERNAL_GROUP_TRAINEE]

    def get_has_score(self, instance):
        return instance.enable_score

    def get_answers_required(self, instance):
        return instance.are_questions_mandatory

    def get_module(self, instance):  # pylint: disable=unused-argument
        return 'workshop'

    def get_preview(self, instance):  # pylint: disable=unused-argument
        return 'workshop-preview.png'

    @staticmethod
    def get_questions(instance):
        """Get the steps of current workshop.

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

        Notes
        -----
        We can't name this method `get_steps` because of compatibility with iOS client.

        Returns
        -------
        list
            Return the steps list.

        """

        steps_queryset = WorkshopStep.objects.non_deleted().filter(
            workshop=instance
        ).order_by('sort_order')

        steps_list = []
        for step in steps_queryset:
            if isinstance(step, WorkshopStepQuestion):
                steps_list.append(
                    CompatibilityWorkshopStepQuestionSerializer(
                        step, read_only=True).data)
            elif isinstance(step, WorkshopStepImage):
                steps_list.append(
                    CompatibilityWorkshopStepImageSerializer(
                        step, read_only=True).data)

        if instance.is_steps_order_random:
            random.shuffle(steps_list)

        return steps_list
