from datetime import datetime

from django import forms
from django.forms import ModelForm, Form
from django.utils.dates import MONTHS

from models import Subject, Worker, Appointment, Visit, AppointmentType
from models.constants import SUBJECT_TYPE_CHOICES

"""
Possible redundancy, but if need arises, contents of forms can be easily customized
"""

CURRENT_YEAR = datetime.now().year
YEAR_CHOICES = tuple(range(CURRENT_YEAR, CURRENT_YEAR - 120, -1))
FUTURE_YEAR_CHOICES = tuple(range(CURRENT_YEAR, CURRENT_YEAR + 5, 1))
DATEPICKER_DATE_ATTRS = {
    'class': 'datepicker',
    'data-date-format': 'yyyy-mm-dd',
    'data-date-orientation': 'bottom'
}
DATETIMEPICKER_DATE_ATTRS = {
    'class': 'datetimepicker',
    'data-date-format': 'Y-MM-DD HH:mm',
}
START_YEAR_STATISTICS = 2015


def validate_subject_nd_number(self):
    subject = self.cleaned_data
    if subject['nd_number'] != "":
        subjects_from_db = Subject.objects.filter(nd_number=subject['nd_number'])
        if subjects_from_db:
            if subjects_from_db[0].screening_number != subject.get('screening_number', ''):
                self.add_error('nd_number', "ND number already in use")


class SubjectAddForm(ModelForm):
    date_born = forms.DateField(label="Date of birth",
                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
                                required=False
                                )

    datetime_contact_reminder = forms.DateField(label="Contact on",
                                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
                                                required=False
                                                )

    class Meta:
        model = Subject
        fields = '__all__'

    def clean(self):
        subject = self.cleaned_data

        subjects_from_db = Subject.objects.filter(screening_number=subject.get('screening_number', ''))

        if len(subjects_from_db) > 0:
            self.add_error('screening_number', "Screening number already in use")

        validate_subject_nd_number(self)


class SubjectDetailForm(ModelForm):
    class Meta:
        model = Subject
        fields = '__all__'


class SubjectEditForm(ModelForm):
    datetime_contact_reminder = forms.DateField(label="Contact on",
                                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
                                                required=False
                                                )
    date_born = forms.DateField(label="Date of birth",
                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
                                required=False
                                )

    def __init__(self, *args, **kwargs):
        super(SubjectEditForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance and instance.id:
            self.fields['screening_number'].widget.attrs['readonly'] = True

    def clean_screening_number(self):
        instance = getattr(self, 'instance', None)
        if instance and instance.id:
            return instance.screening_number
        else:
            return self.cleaned_data['screening_number']

    def clean(self):
        validate_subject_nd_number(self)

    class Meta:
        model = Subject
        fields = '__all__'


class WorkerAddForm(ModelForm):
    class Meta:
        model = Worker
        exclude = ['appointments']


class WorkerDetailForm(ModelForm):
    class Meta:
        model = Worker
        fields = '__all__'


class WorkerEditForm(ModelForm):
    class Meta:
        model = Worker
        fields = '__all__'


class AppointmentDetailForm(ModelForm):
    class Meta:
        model = Appointment
        fields = '__all__'

    datetime_when = forms.DateTimeField(label='Appointment on (YYYY-MM-DD HH:MM)',
                                        widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
                                        )


class AppointmentEditForm(ModelForm):
    class Meta:
        model = Appointment
        fields = '__all__'

    datetime_when = forms.DateTimeField(label='Appointment on (YYYY-MM-DD HH:MM)',
                                        widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
                                        )
    appointment_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
                                                       queryset=AppointmentType.objects.all())

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        if user is None:
            raise TypeError("User not defined")
        self.user = Worker.get_by_user(user)
        if self.user is None:
            raise TypeError("Worker not defined for: " + user.username)

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

    def clean_location(self):
        location = self.cleaned_data['location']
        if self.user.locations.filter(id=location.id).count() == 0:
            self.add_error('location', "You cannot create appointment for this location")
        else:
            return location


class AppointmentAddForm(ModelForm):
    class Meta:
        model = Appointment
        exclude = ['status']

    datetime_when = forms.DateTimeField(label='Appointment on (YYYY-MM-DD HH:MM)',
                                        widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
                                        )
    appointment_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
                                                       queryset=AppointmentType.objects.all())

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        if user is None:
            raise TypeError("User not defined")
        self.user = Worker.get_by_user(user)
        if self.user is None:
            raise TypeError("Worker not defined for: " + user.username)

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

    def clean_location(self):
        location = self.cleaned_data['location']
        if self.user.locations.filter(id=location.id).count() == 0:
            self.add_error('location', "You cannot create appointment for this location")
        else:
            return location


class VisitDetailForm(ModelForm):
    datetime_begin = forms.DateField(label="Visit begins on",
                                     widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
                                     )
    datetime_end = forms.DateField(label="Visit ends on",
                                   widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
                                   )

    post_mail_sent = forms.RadioSelect()
    appointment_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
                                                       queryset=AppointmentType.objects.all())

    class Meta:
        model = Visit
        exclude = ['is_finished']


class VisitAddForm(ModelForm):
    subject = forms.ModelChoiceField(queryset=Subject.objects.order_by('last_name', 'first_name'))
    datetime_begin = forms.DateField(label="Visit begins on",
                                     widget=forms.TextInput(attrs=DATEPICKER_DATE_ATTRS)
                                     )
    datetime_end = forms.DateField(label="Visit ends on",
                                   widget=forms.TextInput(attrs=DATEPICKER_DATE_ATTRS)
                                   )
    appointment_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
                                                       queryset=AppointmentType.objects.all())

    class Meta:
        model = Visit
        exclude = ['is_finished']

    def clean(self):
        if self.cleaned_data['datetime_begin'] >= self.cleaned_data['datetime_end']:
            self.add_error('datetime_begin', "Start date must be before end date")
            self.add_error('datetime_end', "Start date must be before end date")


class KitRequestForm(Form):
    start_date = forms.DateField(label="From date",
                                 widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
                                 required=False
                                 )

    end_date = forms.DateField(label="End date",
                               widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
                               required=False
                               )


class StatisticsForm(Form):
    def __init__(self, *args, **kwargs):
        super(StatisticsForm, self).__init__(*args)
        visit_choices = kwargs['visit_choices']
        month = kwargs['month']
        year = kwargs['year']
        now = datetime.now()
        year_now = now.year
        number_of_years_for_statistics = year_now - START_YEAR_STATISTICS + 2

        year_choices = [(START_YEAR_STATISTICS + i, START_YEAR_STATISTICS + i) for i in
                        range(0, number_of_years_for_statistics + 1)]
        self.fields['month'] = forms.ChoiceField(choices=MONTHS.items(), initial=month)
        self.fields['year'] = forms.ChoiceField(choices=year_choices, initial=year)
        choices = [(-1, "all")]
        choices.extend(SUBJECT_TYPE_CHOICES.items())
        self.fields['subject_type'] = forms.ChoiceField(choices=choices, initial="-1")
        self.fields['visit'] = forms.ChoiceField(choices=visit_choices, initial="-1")