from django import forms
from django.db.models import Q

from projects.models import Project
from .models import Sample
from core.widgets import CustomDateTimeWidget, NumberWithUnitWidget
from bags.models import Bag
from referencegases.models import ReferenceGas


# custom odour sample form to allow for easier cross field validation
class SampleForm(forms.ModelForm):
    class Meta:
        model = Sample
        exclude = []
        widgets = {
            'sampled_at': CustomDateTimeWidget(),
            'factor': NumberWithUnitWidget(suffix='')
        }

    def __init__(self, *args, **kwargs):
        super(SampleForm, self).__init__(*args, **kwargs)
        # restrict choices for pre dilution source, can't pre diluted from self
        self.fields['source_sample'].queryset = Sample.objects.all().exclude(pk=self.instance.pk)

        # depending on edit or create case, we manually apply filters to the choice fields, since
        # limit_choices_to is quite - limited... we want to exclude inactive stuff but retain the
        # current item, even if it is active

        if self.instance.pk is not None:  # update
            # Bag (active and not used) or (current)
            # (note: we can't edit a sample without a bag, so no if-guard necessary)
            self.fields['contained_in'].queryset = \
                Bag.objects.filter((Q(is_active=True) & Q(sample__isnull=True)) | Q(sample__pk=self.instance.pk))
            # cylinder (active and current)
            if self.instance.cylinder:
                self.fields['cylinder'].queryset = \
                    ReferenceGas.objects.filter(Q(is_active=True) | Q(pk=self.instance.cylinder.pk))
            else:
                self.fields['cylinder'].queryset = ReferenceGas.objects.filter(is_active=True)
            # and finally, inactive projects should also not clutter up or stuff
            if self.instance.project:
                self.fields['project'].queryset = \
                    Project.objects.filter(Q(is_active=True) | Q(pk=self.instance.project.pk))
            else:
                self.fields['project'].queryset = Project.objects.filter(is_active=True)
        # create case
        else:
            # for new samples, just use all empty and active bags
            self.fields['contained_in'].queryset = \
                Bag.objects.filter(is_active=True, sample__isnull=True)  # AND
            self.fields['cylinder'].queryset = \
                ReferenceGas.objects.filter(is_active=True)
            self.fields['project'].queryset = \
                Project.objects.filter(is_active=True)

    # make sure to return something useful whatever path we take
    def save(self, commit=True):
        if self.instance.pk is not None and Sample.has_measurement(self.instance.pk):  # editing a sample with ex. meas
            old = Sample.objects.get(id=self.instance.pk)  # check if history affecting fields where changed
            if self.instance.cylinder != old.cylinder \
                    or self.instance.source_sample != old.source_sample \
                    or self.instance.factor != old.factor:
                retval = super(SampleForm, self).save(True)
                from panelists.qualification import update_panel_qualification
                update_panel_qualification()
                return retval
            else:
                return super(SampleForm, self).save(True)
        else:
            return super(SampleForm, self).save(True)
