from django.forms import (
    BaseInlineFormSet,
    Form,
    ModelForm,
    ModelMultipleChoiceField,
    ModelChoiceField,
    ChoiceField,
    CharField,
)
from django.forms import inlineformset_factory
from generic.forms import ExamAuthorFormMixin, ExamFormMixin, ExamGroupsFormMixin, ExamMarkerFormMixin

from longs.models import (
    # Examination,
    AnswerMarks,
    Long,
    LongSeries,
    LongSeriesImage,
    LongCreationDefault,
    UserAnswer,
    Exam,
)

from django.db.models import Prefetch


from anatomy.models import Modality

from generic.models import Examination#, Condition, Sign

# from generic.models import Examination, Site, Condition, Sign

from django.contrib.admin.widgets import FilteredSelectMultiple
from django.forms.widgets import RadioSelect, TextInput, Textarea

from tinymce.widgets import TinyMCE
from generic.widgets import ExamSearchWidget


class LongAnswerForm(ModelForm):
    class Meta:
        model = UserAnswer
        fields = (
            "answer_observations",
            "answer_interpretation",
            "answer_principle_diagnosis",
            "answer_differential_diagnosis",
            "answer_management",
        )


class MarkLongQuestionSingleForm(ModelForm):
    class Meta:
        model = UserAnswer
        fields = ["score", "candidate_feedback", "marker_feedback"]

        widgets = {
            "candidate_feedback": Textarea(attrs={"rows": 3}),
            "marker_feedback": Textarea(attrs={"rows": 3}),
        }

class MarkLongQuestionDoubleForm(ModelForm):
    class Meta:
        model = AnswerMarks
        fields = ["score", "mark_reason"]


class ExaminationForm(ModelForm):
    class Meta:
        model = Examination
        fields = ["examination"]


class LongCreationDefaultForm(ModelForm):
    class Meta:
        model = LongCreationDefault
        # fields = ["site"]
        exclude = ["author"]


class LongSeriesForm(ModelForm):
    class Media:
        # Django also includes a few javascript files necessary
        # for the operation of this form element. You need to
        # include <script src="/admin/jsi18n"></script>
        # in the template.
        css = {
            "all": ["css/widgets.css"],
        }
        # Adding this javascript is crucial
        js = ["jsi18n.js", "tesseract.min.js"]

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop(
            "user"
        )  # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
        if kwargs.get("instance"):
            # We get the 'initial' keyword argument or initialize it
            # as a dict if it didn't exist.
            initial = kwargs.setdefault("initial", {})
            # The widget for a ModelMultipleChoiceField expects
            # a list of primary key for the selected data.
            initial["long"] = [t.pk for t in kwargs["instance"].long.all()]

        super(LongSeriesForm, self).__init__(*args, **kwargs)
        # self.fields["examination"] = ModelChoiceField(
        #    queryset=Examination.objects.all(),
        #    widget=FilteredSelectMultiple(verbose_name="Examination", is_stacked=False),
        # )

        self.fields["modality"] = ModelChoiceField(
            required=True,
            queryset=Modality.objects.all(),
        )

        ModelForm.__init__(self, *args, **kwargs)

        if self.user.groups.filter(name="long_checker").exists():
            long_queryset = Long.objects.all()
        else:
            long_queryset = Long.objects.filter(
                author__id=self.user.id
            ) | Long.objects.filter(open_access=True)

        self.fields["long"] = ModelMultipleChoiceField(
            required=False,
            queryset=long_queryset,
            widget=FilteredSelectMultiple(verbose_name="Long", is_stacked=False),
        )

    def save(self, commit=True):
        # Get the unsaved Pizza instance
        instance = ModelForm.save(self, False)

        # Prepare a 'save_m2m' method for the form,
        old_save_m2m = self.save_m2m

        def save_m2m():
            old_save_m2m()
            # This is where we actually link the pizza with toppings
            instance.long.clear()
            for long in self.cleaned_data["long"]:
                instance.long.add(long)

        self.save_m2m = save_m2m

        # Do we need to save all changes now?
        # if commit:
        instance.save()
        self.save_m2m()

        return instance

    class Meta:
        model = LongSeries
        exclude = ["author"]


class LongForm(ModelForm):

    # exams = ModelMultipleChoiceField(required=False, queryset=Exam.objects.all(),widget=FilteredSelectMultiple(verbose_name="Exams", is_stacked=False))

    class Media:
        # Django also includes a few javascript files necessary
        # for the operation of this form element. You need to
        # include <script src="/admin/jsi18n"></script>
        # in the template.
        css = {
            "all": ["css/widgets.css"],
        }
        # Adding this javascript is crucial
        js = ["jsi18n.js", "tesseract.min.js"]

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop(
            "user"
        )  # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
        if kwargs.get("instance"):
            # We get the 'initial' keyword argument or initialize it
            # as a dict if it didn't exist.
            initial = kwargs.setdefault("initial", {})
            # The widget for a ModelMultipleChoiceField expects
            # a list of primary key for the selected data.
            initial["exams"] = [t.pk for t in kwargs["instance"].exams.all()]


        ModelForm.__init__(self, *args, **kwargs)

        super(LongForm, self).__init__(*args, **kwargs)
        print(self.fields)

        if self.user.groups.filter(name="long_checker").exists():
            exam_queryset = Exam.objects.all()
        else:
            exam_queryset = Exam.objects.filter(
                author__id=self.user.id
            ) | Exam.objects.filter(open_access=True)

        self.fields["exams"] = ModelMultipleChoiceField(
            required=False,
            queryset=exam_queryset,
            widget=ExamSearchWidget(exam_model=Exam),
        )

    class Meta:
        model = Long
        # fields = ['due_back']
        # fields = '__all__'
        fields = [
            # "examination",
            # "site",
            "description",
            "history",
            "feedback",
            #"condition",
            #"sign",
            "model_observations",
            "model_interpretation",
            "model_principle_diagnosis",
            "model_differential_diagnosis",
            "model_management",
            "mark_scheme",
            "open_access",
        ]
        # fields = ['question', 'feedback', 'subspecialty', 'references']
        widgets = {
            # "normal": RadioSelect(
            # choices=[(True, 'Yes'),
            #     (False, 'No')])
            "feedback": TinyMCE(attrs={"cols": 80, "rows": 20}),
            "mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}),
            "description": Textarea(attrs={"cols": 80, "rows": 5}),
            "history": Textarea(attrs={"cols": 80, "rows": 5}),
            "model_observations": Textarea(attrs={"cols": 80, "rows": 5}),
            "model_interpretation": Textarea(attrs={"cols": 80, "rows": 5}),
            "model_principle_diagnosis": Textarea(attrs={"cols": 80, "rows": 5}),
            "model_differential_diagnosis": Textarea(attrs={"cols": 80, "rows": 5}),
            "model_management": Textarea(attrs={"cols": 80, "rows": 5}),
        }

    def save(self, commit=True):
        instance = ModelForm.save(self, False)
        instance.save()

        old_exams = instance.exams.all()

        new_exams = self.cleaned_data["exams"]

        for exam in old_exams:
            if exam not in new_exams:
                exam.exam_questions.remove(instance)

        for exam in new_exams:
            exam.exam_questions.add(instance)
        self.save_m2m()

        return instance

#class CustomInlineFormSet(BaseInlineFormSet):
#    def get_queryset(self):
#        if not hasattr(self, '_queryset'):
#            qs = super(CustomInlineFormSet, self).get_queryset()#.values()
#            self._queryset = qs
#        return self._queryset

#class LongForm(ModelForm):
class CaseSeriesForm(ModelForm):
    def __init__(self, *args, **kwargs):

        super(CaseSeriesForm, self).__init__(*args, **kwargs)
        ModelForm.__init__(self, *args, **kwargs)


        # We can limit the series available to choose from here
        # as well a dramatically reducing the sql queries
        queryset = LongSeries.objects.select_related("modality", "examination", "plane").prefetch_related("long").all()#.filter(pk=62)#.values()
        self.fields["longseries"] = ModelChoiceField(queryset=queryset)

    class Meta:
        model = LongSeries.long.through
        #fields = [ modality ]
        #exclude = []
        fields = ["longseries", "sort_order"]

    


SeriesFormSet = inlineformset_factory(
    Long,
    LongSeries.long.through,
    form=CaseSeriesForm,
    exclude=[],
    can_delete=True,
    extra=0,
    max_num=10,
    #formset=CustomInlineFormSet
)

LongSeriesImageFormSet = inlineformset_factory(
    LongSeries,
    LongSeriesImage,
    exclude=[],
    can_delete=True,
    extra=0,
    max_num=2000,
    field_classes="testing",
)


class ExamForm(ExamFormMixin, ModelForm):
    class Meta(ExamFormMixin.Meta):
        model = Exam
        fields = ExamFormMixin.Meta.fields + ["double_mark"]

class ExamAuthorForm(ExamAuthorFormMixin):
    class Meta(ExamAuthorFormMixin.Meta):
        model = Exam
        #fields = ExamAuthorFormMixin.Meta.fields.append("double_mark")

class ExamMarkerForm(ExamMarkerFormMixin):
    class Meta(ExamMarkerFormMixin.Meta):
        model = Exam

class ExamGroupsForm(ExamGroupsFormMixin):
    class Meta(ExamGroupsFormMixin.Meta):
        model = Exam