import dateutil.parser

from .utils import response_standard
from .constants import STRING, CHOICES
from .models import Entity, Question, AllowedResponse, QuestionSurvey, Observation
    # Notification
import dateutil.parser
import datetime

__author__ = 'aamirbhatt'

class QuestionApi(object):


    def _filter(self, parent_is_null=None, child_is_null=None, study_id=None):
        ques = Question.objects
        if study_id:
            ques = ques.filter(study__id=study_id)
        if child_is_null is True:
            ques = ques.filter(child_of=None)
        if parent_is_null is True:
            ques = ques.filter(parent=None)
        if child_is_null is False:
            ques = ques.exclude(child_of=None)
        if parent_is_null is False:
            ques = ques.exclude(parent=None)
        return ques

    def _get(self, id):
        return Question.objects.get(id=id)

class QuestionSurveyApi(object):
    def _create(self, survey, question, order=None, allows_multiple=False, is_required=False):
        survey = QuestionSurvey(survey=survey, question=question)
        survey.order = order
        survey.allows_multiple = allows_multiple
        survey.is_required = is_required
        survey.save()
        return survey

    def _filter(self, survey_id=None, parent=None, child_of=None, parent_is_null=False):
        if parent_is_null and survey_id:
            return QuestionSurvey.objects.filter(survey=survey_id, question__parent=None).order_by("order")
        if survey_id:
            return QuestionSurvey.objects.filter(survey=survey_id).order_by("order")
        if child_of:
            return QuestionSurvey.objects.filter(question__child_of=child_of).order_by("order")
        return QuestionSurvey.objects.all().order_by("order")

    def _get(self, id):
        return QuestionSurvey.objects.get(id=id)

    def _update(self, id, order=None, is_required=None):
        qs = self._get(id=id)
        if order is not None:
            qs.order = order
        if is_required is not None:
            qs.is_required = is_required
        qs.save()
        return qs

    def _defaultparams(self, obj):
        return {"survey": obj.survey, "question": obj.question, "order": obj.order,
                "allows_multiple": obj.allows_multiple}

    def is_valid(self, obervation, data_type):
        if data_type == "concept":
            value = obervation.get("concept")
        else:
            key = data_type + "_value"
            value = obervation.get(key)
        if value is None or not value.strip():
            return False
        return True

    def _data_type(self, id):
        qs_obj = self._get(id)
        question = qs_obj.question
        data_type = question.data_type
        return data_type

    def _delete(self, id):
        question_survey = QuestionSurvey.objects.get(id=id)
        question_survey.delete()
        return True


class AllowedResponseApi(object):
    def _get(self, id):
        return AllowedResponse.objects.get(id=id)

    def _create(self, question, value, order, icon_name=None, display_name=None, concept=None, is_expected_value=False, participant=None):
        ar, created = AllowedResponse.objects.get_or_create(question=question, value=value, order=order, participant=participant)
        if icon_name:
            ar.icon_name = icon_name
        if display_name:
            ar.display_name = display_name
        if concept:
            ar.concept = concept
        if is_expected_value is not None:
            ar.is_expected_value = is_expected_value
        ar.save()
        return ar

    def _filter(self, question_id, participant=None):
        obj = AllowedResponse.objects.filter(participant=participant)
        if question_id is None:
            return obj
        return obj.filter(question=question_id).order_by('order')

    def _update(self, id, value=None, order=None, display_name=None, is_expected_value=None):
        ar = self._get(id)
        if value:
            ar.value = value
        if display_name:
            ar.display_name = display_name
        if order:
            ar.order = order
        if is_expected_value is not None:
            ar.is_expected_value = is_expected_value
        ar.save()
        return ar

    def _delete(self, id):
        ar = self._get(id)
        ar.delete()

    def _delete_by_participant(self, question, participant, source_question=None):
        AllowedResponse.objects.filter(
            participant=participant, question=question).delete()


class ObservationApi(object):
    def _create(self, question_survey, participant, concept_value=None, parent=None, str_value=None,
                int_value=None, double_value=None, text_value=None, file_value=None, date_value=None,
                entry_date=None, local_timezone=None):
        observation = Observation(question_survey=question_survey, participant=participant)
        if concept_value:
            observation.concept_value = concept_value
        if parent:
            observation.parent = parent
        if str_value:
            observation.str_value = str_value
        if int_value:
            observation.int_value = int_value
        if double_value:
            observation.double_value = double_value
        if text_value:
            observation.text_value = text_value
        if file_value:
            observation.file_value = file_value
        if date_value:
            observation.date_value = date_value
        if entry_date:
            observation.entry_date = entry_date
        if local_timezone:
            observation.local_timezone = local_timezone
        observation.save()
        return observation

    def _filter(self, survey=None, participant=None, entry_date=None, question_survey=None, study=None, 
                start_date=None, end_date=None, question_id=None, survey_id_list=None, parent=None):
        obs = Observation.objects.select_related('parent').all().filter(is_edited=False)
        if survey:
            obs = obs.filter(question_survey__survey__id=survey)
        if survey_id_list:
            obs = obs.filter(question_survey__survey__id__in=survey_id_list)
        if question_survey:
            obs = obs.filter(question_survey__id=question_survey)
        if participant:
            obs = obs.filter(participant__id=participant)
        if study:
            obs = obs.filter(question_survey__survey__study_id=study)
        if question_id:
            obs = obs.filter(question_survey__question__id=question_id)
        if parent or parent == False:
            if parent == False: 
                obs = obs.filter(parent_id__isnull=True)
            else:
                obs = obs.filter(parent_id = parent)
        if start_date is not None:
            obs = obs.filter(
                entry_date__gte=dateutil.parser.parse(start_date.replace(" ", "+"), dayfirst=False) if isinstance(start_date, datetime.datetime) == False else start_date,
                entry_date__lt=dateutil.parser.parse(end_date.replace(" ", "+"), dayfirst=False) if isinstance(end_date, datetime.datetime) == False else end_date)
        else:
            if entry_date:
                obs = obs.filter(entry_date=dateutil.parser.parse(entry_date.replace(" ", "+"), dayfirst=False) if isinstance(entry_date, datetime.datetime) != True and isinstance(entry_date, datetime.datetime) != True else entry_date)

        q = obs.order_by('created_on')
        return q