# various fancy serializers and json-views to make all
# relevant data for external certificate generation available

from rest_framework import generics
from rest_framework import serializers

from projects.models import Project
from samples.models import Sample
from clients.models import ClientOffice
from measurements.models import Measurement
from users.models import WinoseUser

dt_format_certificates = "%Y-%m-%d %H:%M"

# convert various float values to strings, this makes handling different
# locales easier on vba side
class FloatToString(serializers.Field):
    def to_native(self, value):
        if value:
            return str(value)
        else:
            return None


# serialize an image field to its full url
class ImageFieldUrl(serializers.Field):
    def to_native(self, value):
        if value:
            return value.url
        else:
            return None


class UserInformationSerializer(serializers.ModelSerializer):
    signature = ImageFieldUrl()

    class Meta:
        model = WinoseUser
        fields = ['signature', 'position', 'first_name', 'last_name', 'username']


class ProjectClientSerializer(serializers.ModelSerializer):
    client = serializers.RelatedField(many=False)

    class Meta:
        model = Project
        fields = ['id', 'name', 'client', 'reference']


# measurement with all the fancy convenience shit added in
class MeasurementSerializerCert(serializers.ModelSerializer):
    result = FloatToString()
    analysis_result = FloatToString()
    started_at = serializers.DateTimeField(format=dt_format_certificates)
    finished_at = serializers.DateTimeField(format=dt_format_certificates)
    valid_ite_count = serializers.Field()
    unique_panel_count = serializers.Field()
    single_ite_list = serializers.Field()
    rounds_total = serializers.Field()
    rounds_included = serializers.Field()
    comments = serializers.Field()
    upper_lower_limit = serializers.Field()

    class Meta:
        model = Measurement
        fields = ['analysis_result', 'finished_at', 'started_at', 'result', 'rounds_total', 'rounds_included',
                  'valid_ite_count', 'unique_panel_count', 'single_ite_list', 'comments', 'compliant_result',
                  'upper_lower_limit']


class SamplesWithMeasurements(serializers.ModelSerializer):
    total_dilution = serializers.Field()
    contained_in = serializers.RelatedField(many=False)
    sampled_at = serializers.DateTimeField(format=dt_format_certificates)
    measurements = MeasurementSerializerCert(many=True)
    predilution_count_lab = serializers.Field()  # dilution count without dilution at source
    predilution_count_total = serializers.Field()

    class Meta:
        model = Sample
        depth = 1
        fields = ['total_dilution', 'name', 'reference', 'measurements', 'comments',
                  'contained_in', 'sampled_at', 'predilution_count_lab', 'supplier',
                  'predilution_count_total']


class ClientOfficeWithClient(serializers.ModelSerializer):
    class Meta:
        model = ClientOffice
        depth = 1  # recurse into the record of the client (the roof top)
        fields = ['client', 'address', 'address2', 'zip', 'country', 'city', 'phone']


# serialize all the things
# this holds all samples for a project, including all measurements for each sample
# for convenience, a list of all users is added, to get the necessary signer information
class ProjectForCertificateSerializer(serializers.Serializer):
    name = serializers.CharField()
    reference = serializers.CharField()
    contact = serializers.RelatedField(many=False)
    last_changed_at = serializers.Field()
    samples = SamplesWithMeasurements(many=True)
    client = ClientOfficeWithClient(many=False)
    operator_list = serializers.Field()  # all operators participating in this project
    # grab the signature image from this, instead of using the request object which is not working
    # correctly from the word macro :(
    user_list = UserInformationSerializer()
    recent_lab_values = serializers.Field()

    class Meta:
        model = Project
        depth = 1
        fields = ['name', 'client', 'reference', 'samples', 'user_list',
                  'last_changed_at', 'contact', 'operator_list', 'recent_lab_values']


# for project selection in vba form
class ProjectWithClientListView(generics.ListAPIView):
    model = Project
    serializer_class = ProjectClientSerializer
    queryset = Project.objects.filter(is_active=True)  # show active only


# specialized export api used by e.g. word macros and other similar tools
class CertificateRestReport(generics.RetrieveAPIView):
    model = Project
    serializer_class = ProjectForCertificateSerializer
