import re
from Question import Question
from Question import QuestionType

# types = ["multichoice", "truefalse", "shortanswer" , "matching",
# "cloze", "essay", "numerical", "description"]  # These are the possible
# question types in moodle (for reference)

QUESTION_DELIMETER = '^Q.'
ANSWER_DELIMETER = '^A.'
MATCHING_SYMBOL = '->'
CORRECT_ANSWER_SYMBOL = '~'

TRUE_FALSE = ('true', 'false', 't', 'f')
YES_NO = ('yes', 'no', 'y', 'n')

def questions_from_lines(lines):
    split_at_QUESTION_DELIMETERs = get_questions(lines)
    questions = make_questions(split_at_QUESTION_DELIMETERs)
    return questions

def get_questions(lines):
    return re.split(QUESTION_DELIMETER, lines, flags=re.MULTILINE)[1:]

def make_questions(list_of_questions_answers):
    questions = []
    for question_answer in list_of_questions_answers:
        split_at_ANSWER_DELIMETERs = re.split(ANSWER_DELIMETER,
                                              question_answer,
                                              flags=re.MULTILINE)
        # The test of the question_answer is the portion that preceeds
        # the first ANSWER_DELIMETER, with white space stripped:
        question_text = split_at_ANSWER_DELIMETERs[0].strip()

        # The rest of the question_answer is a list of answers.
        # Strip white space from the ends of each answer:
        answers = split_at_ANSWER_DELIMETERs[1:]
        for k in range(len(answers)):
            answers[k] = answers[k].strip()

        # Get the type of question, make a Question, and add to the list:
        question_type = get_question_type(answers)
        question = Question(question_type, question_text, answers)
        questions.append(question)

    return questions


def get_question_type(answers):
    # No answers means Description:
    if len(answers) == 0:
        return QuestionType.description

    # If there is just one answer:
    if len(answers) == 1:

        answer = answers[0].strip()

        # Just white space means Essay.
        if answer == '':
            return QuestionType.essay

        # Just True or False (possibly with a CORRECT_ANSWER_SYMBOL)
        # means True/False:
        if answer.replace(CORRECT_ANSWER_SYMBOL, '').lower() in TRUE_FALSE:
            return QuestionType.truefalse

        # Similarly for just Yes or No:
        if answer.replace(CORRECT_ANSWER_SYMBOL, '').lower() in YES_NO:
            return QuestionType.yesno

        # Otherwise Short Answer (with just one possible answer):
        # CONSIDER: This may conceal an "impossible" answer that is an error.
        return QuestionType.shortanswer

    # If there are multiple answers:

    # If there are just two answers and both are True/False or Yes/No,
    # and exactly one of the two choices has a CORRECT_ANSWER_SYMBOL,
    # that means True/False or Yes/No.
    if len(answers) == 2:
        for question_type in (TRUE_FALSE, YES_NO):
            result = True
            for answer in answers:
                reduced_answer = answer.replace(CORRECT_ANSWER_SYMBOL,
                                                '').lower().strip()
                if reduced_answer not in question_type:
                    result = False
                    break
            if result:
                if ((CORRECT_ANSWER_SYMBOL in answers[0]) !=
                    (CORRECT_ANSWER_SYMBOL in answers[1])):
                    if question_type == TRUE_FALSE:
                        return QuestionType.truefalse
                    else:
                        return QuestionType.yesno

    # MATCHING_SYMBOL in all the answers means Matching:
    matching = True
    for answer in answers:
        if MATCHING_SYMBOL not in answer:
            matching = False
            break
    if matching:
        return QuestionType.matching

    # CORRECT_ANSWER_SYMBOL in NONE of the answers means short answer:
    short_answer = True
    for answer in answers:
        if CORRECT_ANSWER_SYMBOL in answer:
            short_answer = False
            break
    if short_answer:
        return QuestionType.shortanswer

    # Otherwise:  MULTIPLE CHOICE.
    return QuestionType.multichoice

# def format1_to_format2(quiz_number, term=TERM):
#     lines = read_file(quiz_number, term)
#     lines = re.sub(r'^D\.', 'Q.', lines, flags=re.MULTILINE)
#     lines = re.sub(r'^[0-9]+\.', 'Q.', lines, flags=re.MULTILINE)
#     lines = re.sub(r'^[a-z]\.', 'A.', lines, flags=re.MULTILINE)
#     lines = re.sub(r'^ANS\.', 'A.', lines, flags=re.MULTILINE)
#     lines = re.sub(r'^M\.', 'A.', lines, flags=re.MULTILINE)
#     return lines