# coding: utf-8

# This file is part of toutatis.
#
# toutatis is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# toutatis is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>

import representatives_votes.models as models
from rest_framework import serializers

from django.db import transaction


class VoteSerializer(serializers.ModelSerializer):
    '''
    Serializer for votes
    '''
    class Meta:
        model = models.Vote
        fields = (
            'representative_name',
            'representative_remote_id',
            'position'
        )


class ProposalSerializer(serializers.ModelSerializer):
    '''
    Base Proposal Serializer
    '''
    class Meta:
        model = models.Proposal
        fields = (
            'id',
            'fingerprint',
            'title',
            'description',
            'reference',
            'datetime',
            'kind',
            'total_abstain',
            'total_against',
            'total_for',
        )


class ProposalHyperLinkedSerializer(ProposalSerializer):
    '''
    Proposal Serializer with hyperlink to dossier (used for listing)
    '''
    dossier = serializers.HyperlinkedRelatedField(
        read_only = True,
        view_name = 'dossier-detail',
    )
    
    dossier_title = serializers.CharField(
        read_only = True,
        source = 'dossier.title'
    )

    dossier_reference = serializers.CharField(
        read_only = True,
        source = 'dossier.reference'
    )
    
    class Meta(ProposalSerializer.Meta):
        fields = ProposalSerializer.Meta.fields + (
            'dossier',
            'dossier_title',
            'dossier_reference',
            'url',
        )
        
class ProposalDetailSerializer(ProposalSerializer):
    '''
    Proposal Serializer with votes detail (used in Dossier Detail)
    '''
    votes = VoteSerializer(many=True)
    
    class Meta(ProposalSerializer.Meta):
        fields = ProposalSerializer.Meta.fields + (
            'votes',
        )


class ProposalDetailHyperLinkedSerializer(ProposalDetailSerializer, ProposalHyperLinkedSerializer):
    '''
    Proposal Serializer combined Detail Serializer and Hyperlinked Serializer
    '''
    class Meta(ProposalSerializer.Meta):
        fields = ProposalSerializer.Meta.fields + (
            'dossier',
            'dossier_title',
            'dossier_reference',
            'votes',
        )


class DossierSerializer(serializers.ModelSerializer):
    '''
    Base Dossier Serializer
    '''
    class Meta:
        model = models.Dossier
        fields = (
            'id',
            'fingerprint',
            'title',
            'reference',
            'text',
            'link',
        )


class DossierListSerializer(DossierSerializer):
    '''
    Dossier Serializer with short description of proposals
    '''
    class ProposalSerializer(ProposalSerializer):
        class Meta(ProposalSerializer.Meta):
            fields = (
                'id',
                'url',
            ) + ProposalSerializer.Meta.fields
            
    
    proposals = ProposalSerializer(
        many = True,
        read_only = True
    )

    class Meta(DossierSerializer.Meta):
        fields = DossierSerializer.Meta.fields + (
            'url',
            'proposals',
        )


class DossierDetailSerializer(DossierSerializer):
    '''
    Dossier Serializer with proposals details
    '''

    proposals = ProposalDetailSerializer(
        many = True,
    )

    class Meta(DossierSerializer.Meta):
        fields = DossierSerializer.Meta.fields + (
            'proposals',
        )

    @transaction.atomic
    def create(self, validated_data):
        proposals_data = validated_data.pop('proposals')
        dossier, _ = models.Dossier.objects.get_or_create(**validated_data)

        for proposal_data in proposals_data:
            proposal, created = self._create_proposal(
                proposal_data,
                dossier
            )

        return dossier
    
    def _create_proposal(self, proposal_data, dossier):
        votes_data = proposal_data.pop('votes')
        proposal_data['dossier'] = dossier
        proposal, created = models.Proposal.objects.get_or_create(**proposal_data)
        if created:
            for vote_data in votes_data:
                vote_data['proposal'] = proposal
                models.Vote.objects.create(**vote_data)
        return (proposal, created)