from quiz.blueprint.blueprint import BlueprintGroup


class Sheet:
    def __init__(self, question_sheet, solutions_sheet, examinee_inputs, corrections):
        self.question_sheet = question_sheet

        ##answers = solutions + correct_choices
        self.solutions_sheet = solutions_sheet

        self.examinee_inputs = examinee_inputs
        self.corrections = corrections

    @classmethod
    def from_blurprint(cls, blurprint):
        question_sheet = QuestionSheet.from_blurprint(blurprint)
        solutions_sheet = SolutionSheet.from_blurprint(blurprint)
        return cls(
            question_sheet=question_sheet,
            solutions_sheet=solutions_sheet,
            examinee_inputs=None,
            corrections=None
        )

    @classmethod
    def from_exam_page(cls, exam_page):
        question_sheet = QuestionSheet.from_dict(exam_page.questionnaire)
        solutions_sheet = [Answer.from_dict(item) for item in exam_page.answers]
        examinee_inputs = [ExamineeInput.from_dict(item)
                           for item in exam_page.examinee_inputs]

        from exam.models import Corrections
        corrections = Corrections.objects.filter(exam_page=exam_page)
        return cls(
            question_sheet=question_sheet,
            solutions_sheet=solutions_sheet,
            examinee_inputs=examinee_inputs,
            corrections=corrections
        )


class QuestionSheet:
    def __init__(self, questions, groups):
        self.questions = questions
        self.groups = groups

    @classmethod
    def from_blurprint(cls, blueprint):
        groups = blueprint.groups
        retrievers = blueprint.retrievers
        questionnaire_tems = []

        index = 0

        for retriever in retrievers:
            contents = retriever.contents
            for content in contents:
                questionnaire_tems.append(QuestionnaireItem.from_question_obj(index, content, retriever))
                index += 1

        return cls(
            questions=questionnaire_tems,
            groups=groups
        )

    @classmethod
    def from_dict(cls, input):

        return cls(
            questions=[QuestionnaireItem.from_dict(item) for item in input["questions"]],
            groups=[BlueprintGroup.from_dict(item) for item in input["groups"]]
        )

    def to_dict(self):
        return {
            "questions": [question.to_dict() for question in self.questions],
            "groups": [group.to_dict() for group in self.groups],
        }

    def questions_count(self):
        return len(self.questions)


class SolutionSheet:
    def __init__(self, solutions):
        self.solutions = solutions

    @classmethod
    def from_blurprint(cls, input):
        retrievers = input.retrievers
        answer_items = []

        index = 0

        for retriever in retrievers:
            contents = retriever.contents
            for content in contents:
                answer_items.append(Answer.from_question_obj(index, content))
                index += 1

        return cls(
            solutions=answer_items
        )

    # @classmethod
    # def from_dict(cls, input):
    #
    #     return cls(
    #         solutions=[Answer.from_dict(item) for item in input["questions"]]
    #     )

    def to_dict(self):
        return {
            "solutions": [answer.to_dict() for answer in self.solutions],
        }


class QuestionnaireItem:
    def __init__(self, index, format, question_text, choices, input_rules, question_type, duration, positive_score,
                 negative_score):
        self.index = index
        self.format = format
        self.question_text = question_text
        self.choices = choices
        self.input_rules = input_rules
        self.question_type = question_type
        self.duration = duration
        self.positive_score = positive_score
        self.negative_score = negative_score

    @classmethod
    def from_question_obj(cls, index, obj, retriever):
        return cls(index=index, format=obj.format, question_text=obj.question_text, choices=obj.choices,
                   input_rules=obj.input_rules, question_type=obj.question_type, duration=retriever.duration,
                   positive_score=retriever.positive_score,
                   negative_score=retriever.negative_score)

    @classmethod
    def from_dict(cls, input):
        return cls(index=input['index'], format=input['format'], question_text=input['question_text'],
                   choices=input['choices'], input_rules=input['input_rules'], question_type=input["question_type"],
                   duration=input["duration"], positive_score=input["positive_score"], negative_score=input["negative_score"])

    def to_dict(self):
        return {
            "index": self.index,
            "format": self.format,
            "question_text": self.question_text,
            "choices": self.choices,
            "input_rules": self.input_rules,
            "question_type": self.question_type,
            "duration": self.duration,
            "positive_score": self.positive_score,
            "negative_score": self.negative_score,
        }


class Answer:
    def __init__(self, index, question_id, solution, correct_choices):
        self.index = index
        self.question_id = question_id
        self.solution = solution
        self.correct_choices = correct_choices

    def to_dict(self):
        return {
            "index": self.index, "question_id": self.question_id, "solution": self.solution,
            "correct_choices": self.correct_choices
        }

    @classmethod
    def from_dict(cls, input):
        return cls(
            index=input['index'],
            question_id=input['question_id'],
            solution=input['solution'],
            correct_choices=input['correct_choices'],
        )

    @classmethod
    def from_question_obj(cls, index, obj):
        return cls(
            index=index,
            question_id=str(obj.id),
            solution=obj.solution,
            correct_choices=obj.correct_choices,
        )


class ExamineeInput:
    def __init__(self, g_index, q_index, text, selected_choices, created_at):
        self.g_index = g_index
        self.q_index = q_index
        self.text = text
        self.selected_choices = selected_choices,
        self.created_at = created_at

    def to_dict(self) -> dict:
        return {
            "g_index": self.g_index,
            "q_index": self.q_index,
            "text": self.text,
            "selected_choices": self.selected_choices,
            "created_at": self.created_at,
        }

    @classmethod
    def from_dict(cls, input):
        return cls(
            g_index=input['g_index'],
            q_index=input['q_index'],
            text=input['text'],
            selected_choices=input['selected_choices'],
            created_at=input['created_at'],
        )
