/// <reference path="../references.js" />

var Quiz = Quiz || {};

Quiz.element_counter = 0;
Quiz.CONTAINER_DIV = "<div></div>";
Quiz.CONTAINER_LABEL = "<label></label>";
Quiz.CONTAINER_LINK = "<a class='waves-effect btn'></a>";
Quiz.CONTAINER_LINK2 = '<a class="collection-item waves-effect quizz row" style="width:100%;"></a>';
Quiz.CONTAINER_OVERVIEW_LINK = '<div class="collection-item waves-effect" style="width:100%;"></div>';
Quiz.CONTAINER_SINGLE = "<fieldset data-role='controlgroup' data-mini='true'></fieldset>";
Quiz.CONTAINER_RADIO = "<input type='radio'/>";
Quiz.CONTAINER_CHECKBOX = "<input type='checkbox'/>";
Quiz.CONTAINER_SELECT = "<select></select>";
Quiz.CONTAINER_OPTION = "<option></option>";
Quiz.CONTAINER_NEW_LINE = "<br/>";
Quiz.CONTAINER_LIST_VIEW = "<div class='collection'></div>";
Quiz.CONTAINER_LIST_ITEM = "<div class='collection-item'></div>";
Quiz.CONTAINER_LIST_DIVIDER = "<div class='collection-item'></div>";
Quiz.CONTAINER_BOLD = "<b></b>";
Quiz.CONTAINER_CARD = "<div class='card' style='overflow:visible;'></div>";
Quiz.CONTAINER_CARD_CONTENT = "<div class='card-content'></div>";
Quiz.CONTAINER_CARD_TITLE = "<span class='card-title quiz_head'></span>";
Quiz.CONTAINER_QUIZ_QUESTION = "<blockquote></blockquote>";
Quiz.CONTAINER_ROW = "<div class='row'></div>";
Quiz.CONTAINER_COL = "<div class='col s6'></div>";
Quiz.CONTAINER_RESULT_HEAD = "<div class='quiz_head'></div>";


Quiz.UI = Quiz.UI || {};
Quiz.Configuration = Quiz.Configuration || {};

Quiz.Configuration = function (config_name, setup) {
	var setup = setup || {},
        text = setup.text,
        random = setup.random,
        group_id = setup.group_id,
        type = setup.type,
        id = setup.id,
        courseId = setup.courseId,
        quiz_question_css = { "margin-bottom": "20px","text-align": "left" },
        quiz_response_css = { "display": "none", "background-color": "#f0f0f0", "color": "#ffffff", "border": "0px solid black", "margin": "8px", "margin-bottom": "10px", "padding": "10px", "text-align": "left" },
        quiz_answer_css = { "margin-top":"15px"},
        quiz_answer_last_css = { "margin-top": "15px","margin-bottom":"15px" },
        sub_img_css = { "max-width": "80%", "display": "block", "margin": "auto" },
		config = {};

	if (config_name == "QUIZ_ANSWER") config = { container: Quiz.CONTAINER_DIV, sub_img_css: sub_img_css, css: quiz_answer_css };
	if (config_name == "QUIZ_ANSWER_LAST") config = { container: Quiz.CONTAINER_DIV, sub_img_css: sub_img_css, css: quiz_answer_last_css };
	else if (config_name == "QUIZ_RESPONSE") config = { container: Quiz.CONTAINER_DIV, sub_img_css: sub_img_css, css: quiz_response_css };
	else if (config_name == "QUIZ_BUTTON_NEXT") config = { container: Quiz.CONTAINER_LINK, html: '<i class="material-icons right" style="margin-left:0;">chevron_right</i>'+rwthapp.langStrings.quiz.quiz_next, "data-role": "button", "onclick": "Quiz.Mediator.next();", css: {"width":"100%" } };
	else if (config_name == "QUIZ_BUTTON_BACK") config = { container: Quiz.CONTAINER_LINK, html: '<i class="material-icons left" style="margin-right:0;">chevron_left</i>' + rwthapp.langStrings.quiz.quiz_previous, "data-role": "button", "onclick": "Quiz.Mediator.previous();", css: { "width": "100%" } };
	else if (config_name == "QUIZ_QUESTION") config = { container: Quiz.CONTAINER_QUIZ_QUESTION, html: text, sub_img_css: sub_img_css, css: quiz_question_css };
	else if (config_name == "QUIZ_BUTTON_END") config = { container: Quiz.CONTAINER_LINK, html: rwthapp.langStrings.quiz.quiz_end, "data-role": "button", onclick: "Quiz.Mediator.end();", css: { "width": "100%" } };
	else if (config_name == "QUIZ_ANSWER_CONTAINER") config = { container: Quiz.CONTAINER_DIV, css: { } };
	else if (config_name == "QUIZ_ANSWER_STRING") config = { container: Quiz.CONTAINER_DIV };
	else if (config_name == "QUIZ_ANSWER_STRING_ACTIVE") config = { html: text, css: { "color": "#777", "font-weight": "bold", "text-align": "left", "margin-top": "10px", "margin-bottom": "5px", "padding": "5px", "background-color": "#ffffff", "border-top": "1px solid #ccc" } };
	else if (config_name == "QUIZ_RESULTS") config = { container: Quiz.CONTAINER_DIV };
	else if (config_name == "QUIZ_RESULT_LIST") config = { container: Quiz.CONTAINER_LIST_VIEW };
	else if (config_name == "QUIZ_RESULT_LIST_ITEM") config = { container: Quiz.CONTAINER_LIST_ITEM, html: text };
	else if (config_name == "QUIZ_RESULT_LINK") config = { container: Quiz.CONTAINER_LINK2, html: '<div class="col s9">' + text + '</div><i class="material-icons col s3" style="text-align:right">chevron_right</i>', onclick: "Quiz.Mediator.goToQuestion(" + id + ")", css: { width: "100%" } };
	else if (config_name == "QUIZ_LABEL") config = { container: Quiz.CONTAINER_LABEL, html: text, "for": "choice" + random, css: {"top":"0px !important"} };
	else if (config_name == "QUIZ_ELEMENT") config = { container: type, id: "choice" + random, name: "choice" + group_id, css: { } };
	else if (config_name == "QUIZ_OPTION") config = { container: Quiz.CONTAINER_OPTION, html: text, value: text };
	else if (config_name == "QUIZ_RESPONSE_RIGHT") config = { html: text, css: { "display": "block", "color": "#00cc00" } };
	else if (config_name == "QUIZ_RESPONSE_WRONG") config = { html: text, css: { "display": "block", "color": "#ff0000" } };
	else if (config_name == "QUIZ_LIST_DIVIDER") config = { container: Quiz.CONTAINER_LIST_DIVIDER, html: text, css: { "font-size": "14px", "background-color": "#ffffff" } };  
    else if (config_name == "QUIZ_OVERVIEW_LINK") config = { container: Quiz.CONTAINER_DIV, html: text+'<a class="secondary-content"><i class="material-icons">send</i></a>', onclick: "Quiz.Mediator.load(\"" + courseId + "\",\"" + id + "\")"};
    else if (config_name == "QUIZ_ELEMENT_DISABLED") config = { "disabled": "" };
    else if (config_name == "QUIZ_CARD") config = { container: Quiz.CONTAINER_CARD };
    else if (config_name == "QUIZ_CARD_CONTENT") config = { container: Quiz.CONTAINER_CARD_CONTENT };
    else if (config_name == "QUIZ_CARD_TITLE") config = { container: Quiz.CONTAINER_CARD_TITLE, css: { "color": "#000000" } };
    else if (config_name == "QUIZ_ROW") config = { container: Quiz.CONTAINER_ROW };
    else if (config_name == "QUIZ_COL") config = { container: Quiz.CONTAINER_COL };
    else if (config_name == "QUIZ_RESULT_HEAD") config = { container: Quiz.CONTAINER_RESULT_HEAD, css: { "font-size": "24px", "font-weight": "300", "padding": "20px" } };

	return config;
};

Quiz.Overview = Quiz.Overview || {};

Quiz.UI.Element = function (conf, children) {
	Object.defineProperty(this, 'id', { value: Quiz.element_counter++ });
	this.container_prototype = conf.container;
	delete conf.container;
	this.container = {};
	this.conf = conf;
	this.children = children || [];
	this.build();
};

Quiz.UI.Element.prototype = {
	getDOM: function () {
		return this.container;
	},
	build: function (rebuild) {
		var key = "",
			container = rebuild ? this.container : this.container = $(this.container_prototype),
			c = this.conf,
			children = this.children;

		if (c && c.html) {
            
		    var f = function () {
		        container.html(c.html);
		    };
		    if (rwthapp.platformInfo.isWindowsUniversal()) {
		        MSApp.execUnsafeLocalFunction(f);
		    } else {
		        f();
		    }
		}
		for (key in c) {
			if (key === "html") continue;
			if (key == "container") continue;
			else if (key === "css") container.css(c[key]);
			else if (key === "sub_img_css") {
				container.find("img").css(c[key]);
			}
			else if (key === "disabled") container.prop('disabled', true);
			else container.attr(key, c[key]);
		}

		for (key in children) {
			if (typeof children[key] !== "function") {
				children[key].build(rebuild);
				var x = children[key].getDOM();
				container.append(x);
			}
		}

		return this;
	},
	append: function (element) {
		this.children.push(element);
		this.build();
	},
	change: function (new_conf) {
		var c = this.conf,
			key = "";

		for (key in new_conf) {
			c[key] = new_conf[key];
		}
		this.build(true);
	},
	hide: function (direct) {
		if (direct) {
			this.container.css("display", "none");
		}
		else {

			this.container.fadeOut(90);
		}
	},
	show: function (direct) {
		if (direct) {
			this.container.css("display", "");
		}
		else {

			this.container.fadeIn(90);
		}
	}
};



Quiz.UI.QuizPage = function (heading, question, answers, type, multi_answers, is_first) {
	var random = Math.random(),
		tmp_answers = [],
		i = answers.length, last = true;
	this.conf = {};
	this.container_prototype = Quiz.CONTAINER_DIV;
	this.container = {};
	this.heading = heading;
	this.type = type;
	while (i--) {
		tmp_answers.unshift(new Quiz.UI.QuizAnswer(answers[i], type, random, multi_answers, last));
		last = false;
	}
	this.outerCard = new Quiz.UI.Element(Quiz.Configuration("QUIZ_CARD"));
	this.cardTitle = new Quiz.UI.Element(Quiz.Configuration("QUIZ_CARD_TITLE"));
	this.cardContent = new Quiz.UI.Element(Quiz.Configuration("QUIZ_CARD_CONTENT"));
	this.question = new Quiz.UI.Element(Quiz.Configuration("QUIZ_QUESTION", { text: question }));
	this.answers = new Quiz.UI.Element(Quiz.Configuration("QUIZ_ANSWER_CONTAINER"), tmp_answers);
	this.answer_string = new Quiz.UI.Element(Quiz.Configuration("QUIZ_ANSWER_STRING"));

	this.row = new Quiz.UI.Element(Quiz.Configuration("QUIZ_ROW"));
	this.col1 = new Quiz.UI.Element(Quiz.Configuration("QUIZ_COL"));
	this.col2 = new Quiz.UI.Element(Quiz.Configuration("QUIZ_COL"));

	this.row.children = [this.col1, this.col2];

	this.cardContent.children = [this.cardTitle, this.question, this.answers, this.answer_string];
	this.outerCard.children = [this.cardContent];

	this.button = new Quiz.UI.Element(Quiz.Configuration("QUIZ_BUTTON_NEXT"));
	this.back_button = is_first ? {} : new Quiz.UI.Element(Quiz.Configuration("QUIZ_BUTTON_BACK"));

	this.col1.children = [this.back_button];

	if (!is_first) {
	    this.col1.children = [this.back_button];
	    this.col2.children = [this.button];
	    this.children = [this.outerCard, this.row];
	}
	else {
	    this.col1.children = [this.button];
	    this.children = [this.outerCard,this.row];
	}
	this.build();
};
Quiz.UI.QuizPage.prototype = Object.create(Quiz.UI.Element.prototype);
Quiz.UI.QuizPage.prototype.constructor = Quiz.UI.QuizPage;

Quiz.UI.QuizPage.prototype.getResult = function () {
	var result = [];
	for (var i = 0, max = this.answers.children.length; i < max; i++) {
		result.push(this.answers.children[i].getValue());
	}
	return result;
};

Quiz.UI.QuizPage.prototype.setAnswerString = function (text) {
	this.answer_string.change(Quiz.Configuration("QUIZ_ANSWER_STRING_ACTIVE", { text: text }));
};

Quiz.UI.QuizPage.prototype.getAnswers = function () {
	return this.answers.children;
};

Quiz.UI.QuizPage.prototype.lock = function () {
	for (var i = 0, max = this.answers.children.length; i < max; i++) {
		this.answers.children[i].children[0].change(Quiz.Configuration("QUIZ_ELEMENT_DISABLED"));
	}
};

Quiz.UI.ResultPage = function () {
	this.container_prototype = Quiz.CONTAINER_DIV;
	this.conf = {};
	this.container = {};
	this.children = [];
	this.button = new Quiz.UI.Element(Quiz.Configuration("QUIZ_BUTTON_END"));
	this.results = new Quiz.UI.Element(Quiz.Configuration("QUIZ_RESULTS"));
	this.children = [new Quiz.UI.Element(Quiz.Configuration("QUIZ_RESULT_HEAD")),this.results, this.button];
	this.build();
};

Quiz.UI.ResultPage.prototype = Object.create(Quiz.UI.Element.prototype);
Quiz.UI.ResultPage.prototype.constructor = Quiz.UI.ResultPage;
Quiz.UI.ResultPage.prototype.init = function (result_list) {
	var i = result_list.length, max = result_list.length, sum_points = 0, sum_max = 0, text;
	this.results.children.push(new Quiz.UI.Element(Quiz.Configuration("QUIZ_RESULT_LIST")));
	while (i--) {
		text = rwthapp.langStrings.quiz.quiz_question + " " + (max - i) + ": " + result_list[i].points.toFixed(2) + "/" + result_list[i].max.toFixed(2) + "<p>\"" + Quiz.Mediator.getPage(max - i - 1).heading + "\"</p>";
		this.results.children[0].children.push(new Quiz.UI.Element(Quiz.Configuration("QUIZ_RESULT_LINK", { text: text, id: max - (i + 1) })));
		sum_points += result_list[i].points;
		sum_max += result_list[i].max;
	}
	text = rwthapp.langStrings.quiz.quiz_points + ": " + ((sum_points).toFixed(2)) + "/" + sum_max.toFixed(2);
	this.results.children[0].children.push(new Quiz.UI.Element(Quiz.Configuration("QUIZ_LIST_DIVIDER", { text: text })));
	this.build(true);
    // Perform postprocessing (fixing icons, removing waves effect) if necessary
	rwthapp.templateRenderer.performPostprocessing();
};



Quiz.UI.QuizAnswer = function (label_text, type, group_id, multi_answers, last) {
	var random = Math.random(),
		i = multi_answers ? multi_answers.length : 0;
	this.options = [];
	this.container_prototype = Quiz.CONTAINER_DIV;
	this.container = {};
	if (type == "radio") this.type = Quiz.CONTAINER_RADIO;
	else if (type == "checkbox") this.type = Quiz.CONTAINER_CHECKBOX;
	else if (type == "select") {
	    this.type = Quiz.CONTAINER_SELECT;
		while (i--) {
			this.options.unshift(new Quiz.UI.Element(Quiz.Configuration("QUIZ_OPTION", { text: multi_answers[i] })));
		}
	}
	this.conf = Quiz.Configuration(last ? "QUIZ_ANSWER_LAST" : "QUIZ_ANSWER");
	if (type == "select") this.conf["class"] = "input-field";
	this.children = [new Quiz.UI.Element(Quiz.Configuration("QUIZ_ELEMENT", { type: this.type, random: random, group_id: group_id }), this.options),
					 new Quiz.UI.Element(Quiz.Configuration("QUIZ_LABEL", { text: label_text, random: random, type: type })), ];
	this.response = [new Quiz.UI.Element(Quiz.Configuration("QUIZ_RESPONSE"), [])];
	this.children.push(this.response[0]);
	this.build();
};
Quiz.UI.QuizAnswer.prototype = Object.create(Quiz.UI.Element.prototype);
Quiz.UI.QuizAnswer.prototype.constructor = Quiz.UI.QuizAnswer;

Quiz.UI.QuizAnswer.prototype.getValue = function () {
	return this.type == Quiz.CONTAINER_SELECT ? this.children[0].getDOM().val() : this.children[0].getDOM().prop("checked");
};

Quiz.UI.QuizAnswer.prototype.showResponse = function (is_right, feedback, selected) {
	var i = 1, feedback_2 = "";
	while (i--) {
		if (this.type == Quiz.CONTAINER_CHECKBOX && feedback == "" &&selected==true) {
			feedback_2 = is_right ? rwthapp.langStrings.quiz.quiz_right : rwthapp.langStrings.quiz.quiz_wrong;
			this.response[i].change(Quiz.Configuration(is_right ? "QUIZ_RESPONSE_RIGHT" : "QUIZ_RESPONSE_WRONG", { text: feedback_2 }));
		} else if (this.type == Quiz.CONTAINER_RADIO && feedback == "" && selected == true) {
			feedback_2 = is_right ? rwthapp.langStrings.quiz.quiz_right : rwthapp.langStrings.quiz.quiz_wrong;
			this.response[i].change(Quiz.Configuration(is_right ? "QUIZ_RESPONSE_RIGHT" : "QUIZ_RESPONSE_WRONG", { text: feedback_2 }));
		} else if (feedback != "") this.response[i].change(Quiz.Configuration(is_right ? "QUIZ_RESPONSE_RIGHT" : "QUIZ_RESPONSE_WRONG", { text: feedback }));
	}
};

Quiz.Result = function (answer_count, type) {
	var i = 0;
	this.type = type;
	this.answer_count = answer_count;
	this.feedback = [];
	this.points = [];
	this.right_answers = [];
	this.user_answers = [];
	this.ids = [];
	this.max=0;
};

Quiz.Result.prototype = {
	setSystemPart: function (i, id, right_answer, feedback, points, max) {
		this.right_answers[i] = right_answer;
		this.feedback[i] = feedback;
		this.points[i] = points;
		this.ids[i] = id;
		this.max = max;
	},
	setUserPart: function (i, answer) {
		this.user_answers[i] = answer;
	},
	getUserPart: function (i) {
		return this.user_answers[i];
	},
	isRight: function (i) {
		return this.user_answers[i] === this.right_answers[i];
	},
	selected: function (i) {
		return this.user_answers[i] == true;
	},
	getPoints: function (i) {
		return this.points[i];
	},
	getFeedback: function (i) {
		var s = this.isRight(i) ? rwthapp.langStrings.quiz.quiz_right : rwthapp.langStrings.quiz.quiz_wrong2 + ": " + this.right_answers[i];
		return this.user_answers[i] === true ? this.feedback[i] : (this.type == "select" ? s : "");
	},
	getRightAnswers: function () {
		var tmp = "",
			i = this.answer_count,
			a = this.right_answers;
		while (i--) {
			if (a[i] != "false") tmp = i + (a[i] == "true" ? "," : ": " + a[i]);
		}
		return tmp;
	},
	getRightAnswerString: function () {
		var tmp = "",
            i = this.answer_count,
            a = this.right_answers;
		while (i--) {
			tmp = (a[i] == true ? rwthapp.langStrings.quiz.quiz_answer + " " + (i + 1) + ", " : "") + tmp;
		}
		tmp = rwthapp.langStrings.quiz.quiz_correct_answers + ": " + tmp.substring(0, tmp.length - 2);
		return tmp;
	}
};

Quiz.Evaluator = function () {
	this.results = [];
};

Quiz.Evaluator.prototype = {
	addResult: function (result) {
		this.results.unshift(result);
	},
	setUserPart: function (i, j, answer) {
		this.results[i].setUserPart(j, answer);
	},
	getPointsForQuestion: function (i) {
		var tmp = this.results[i], j = this.results[i].answer_count, points = 0, type = this.results[i].type;
		//All or Nothing Evaluation / Maybe altered later
		while (j--) {
			points += tmp.getPoints(j) * (type != "select" ? tmp.getUserPart(j) : (tmp.isRight(j) ? 1 : 0));
		}
		return points > 0 ? points : 0;
	},
	getMaxPointsForQuestion: function (i) {
		var tmp = this.results[i], j = this.results[i].answer_count, points = 0;
		return tmp.max;
	},
	evaluate: function (quiz) {
		var i = quiz.page_count - 1, j = 0, tmp = [], tmp2 = {}, cor = {};
		while (i--) {
			if (quiz.pages[i].type != "select") quiz.pages[i].setAnswerString(this.getRightAnswerString(i));
			tmp = quiz.pages[i].getAnswers();
			j = tmp.length;
			while (j--) {
				cor = this.getCorrection(i, j);
				tmp[j].showResponse(cor.is_right, cor.feedback, cor.sel);
			}
		}
	},
	getCorrection: function (i, j) {
		return { is_right: this.results[i].isRight(j), feedback: this.results[i].getFeedback(j), sel: this.results[i].selected(j) };
	},
	getResultList: function () {
		var result_list = [], i = this.results.length;
		while (i--) {
			result_list.push({ points: this.getPointsForQuestion(i), max: this.getMaxPointsForQuestion(i) });
		}
		return result_list;
	},
	getRightAnswerString: function (i) {
		return this.results[i].getRightAnswerString();
	}
};

Quiz.Logic = function (pages) {
	this.pages = pages || [];
	this.page_count = pages.length;
	this.parent = $("#quizContent");
	this.parent.html("");
};

Quiz.Logic.prototype = {
	setup: function () {
		var i = this.page_count;
		while (i--) {
			this.parent.prepend(this.pages[i].getDOM());
			this.pages[i].hide(true);
		}
	},
	resume: function () {
		var tmp = $("#quizContent");
		tmp.append(this.parent.children());
		this.parent = tmp;
		$('select').material_select();
	},
	hidePage: function (i, direct) {
		this.pages[i].hide(direct);
	},
	showPage: function (i, direct) {
		if (i < this.page_count - 1) $(".quiz_head").text(rwthapp.langStrings.quiz.quiz_question + " " + (i + 1) + "/" + (this.page_count - 1));
		else $(".quiz_head").text(rwthapp.langStrings.quiz.quiz_evaluation);
		this.pages[i].show(direct);
		$(window).scrollTop(0);
	},
	getUserResult: function (i) {
		if (i >= 0) {
			var page = this.pages[i];
			return page.getResult();
		}
	},
	lockAllPages: function () {
		var i = this.pages.length - 1;
		while (i--) this.pages[i].lock();
		$('select').material_select();
	}
};

Quiz.shuffle = function (ar) {
	var i = ar.length;
	while (--i) {
	    var j = Math.floor(Math.random() * (i + 1));
		var temp = ar[i];
		ar[i] = ar[j];
		ar[j] = temp;
	}

	return ar; // for convenience, in case we want a reference to the array
};

Quiz.Mediator = {
    id: -1,
    courseId: "",
    running: false,
    position: -1,
    quiz: {},
    max_points: 0,
    eval_mode: false,
    evaluator: {},
    cache: {},
    online: false,
    htmlcache: "",
    main:true,
    setup: function (json) {
        this.position = -1;
        this.quiz = {};
        this.user_results = [];
        this.max_points = 0;
        this.max_points = json["maxScore"];
        this.evaluator = new Quiz.Evaluator();
        this.eval_mode = false;
        if (!json["questionList"]) {
            throw new Error(rwthapp.localization.getLocalizedString("errors.quiz.quizNoQuestions"));
        }
        var questions = [], i = json["questionList"].length, j = 0, title = "",
            question = "", answers = [], type = "", multi_answers = [], questionData = {}, answerData = {}, result = {}, right_answer = "", co = 0, q_max_points = 0, questionDisplayTitle="";

        // iterate over questionlist
        while (i--) {
            answers = []; multi_answers = []; questionData = json["questionList"][i];

            // collect data for further processes
            title = questionData["title"];
            questionDisplayTitle = questionData["question"];
            q_max_points = questionData["maxPoints"];

            // map question type to display mode
            if (questionData["type"] == "Complex") {

                type = "select";
            }
            else if (questionData["type"] == "Single") {

                type = "radio";
            }
            else if (questionData["type"] == "Multi") {

                type = "checkbox";
            }

            // shuffle answers for different sequence
            questionData["answers"] = Quiz.shuffle(questionData["answers"]);

            // what does multiAnswers do? Why is only first answer of an question processed?
            if (questionData["answers"][0].multiAnswers) {

                for (co = 0; co < questionData["answers"][0].multiAnswers.length; co++) {

                    multi_answers.unshift(questionData["answers"][0].multiAnswers[co].split("$$")[0]);
                }
            }

            // delete answers without an answer text
            for (j = 0; j < questionData["answers"].length; j++) {

                if (questionData["answers"][j].answerText == "") {

                    questionData["answers"].splice(j, 1);
                }
            }

            j = questionData["answers"].length;
            result = new Quiz.Result(j, type);

            // set result meta-data and collect answers
            while (j--) {
                answerData = questionData["answers"][j];
                right_answer = answerData.multiAnswers ? answerData.multiAnswers[questionData["answers"][j]["answerRightValue"] - 1].split("$$")[0] : (answerData.answerPoints > 0);
                result.setSystemPart(j, answerData.answerId, right_answer, answerData.answerResponse, !answerData.multiAnswers ? answerData.answerRightValue * q_max_points : (1.0 / questionData["answers"].length) * q_max_points, q_max_points);
                answers.unshift(answerData.answerText);
            }

            var unique = [];
            $.each(multi_answers, function (i, el) {
                if ($.inArray(el, unique) === -1) unique.push(el);
            });

            // create QuizPage from the collected data. This structure is displayed on screen. It will be hidden and fadeIn/Out at the right time
            questions.unshift(new Quiz.UI.QuizPage(title, questionDisplayTitle, answers, type, unique, i == 0));
            this.evaluator.addResult(result);
        }
        if (questions.length == 0) {
            throw new Error(rwthapp.localization.getLocalizedString("errors.quiz.quizNoQuestions"));
        }
        // add ResultPage which displays calculated quiz result
        questions.push(new Quiz.UI.ResultPage());
        this.quiz = new Quiz.Logic(questions);

        this.cache[this.courseId + " " + this.id] = json;

        this.saveCache();
        //rwthapp.helper.hide_Loading_Screen();
        // puts all QuizPage instances to the dom and hides them
        this.quiz.setup();
        $('select').material_select();
        // Perform postprocessing (fixing icons, removing waves effect) if necessary
        rwthapp.templateRenderer.performPostprocessing();
        this.running = true;
        // fadeIn first QuizPage
        this.next();
    },
    next: function () {
        var i = 0, tmp = [], result = {};
        this.position += 1;
        if (this.position > 0 && (this.position < this.quiz.pages.length) && !this.eval_mode) {
            tmp = this.quiz.getUserResult(this.position - 1);
            i = tmp.length;
            while (i--) {
                this.evaluator.setUserPart(this.position - 1, i, tmp[i]);
            }
        }
        if (this.position > this.quiz.pages.length - 2 && !this.eval_mode) {
            this.quiz.hidePage(this.quiz.pages.length - 2, true);
            this.evaluate();
        } else {
            if (this.position > 0) {
                var that = this;
                this.quiz.hidePage(this.position - 1);
                setTimeout(function () {
                    that.quiz.showPage(that.position, that.eval_mode);
                }, 90);
            } else if (this.eval_mode) {
                this.quiz.hidePage(this.quiz.pages.length - 1, true);
                this.quiz.showPage(this.position, this.eval_mode);
            } else if (this.position == 0) {
                this.quiz.showPage(this.position, this.eval_mode);
            }
        }
    },
    previous: function () {
        var that = this;
        if (this.position >= 1) {
            this.position -= 1;
            setTimeout(function () { that.quiz.showPage(that.position, that.eval_mode); }, 90);
            if (this.position + 1 < this.quiz.pages.length) this.quiz.hidePage(this.position + 1);
            else if (this.eval_mode) this.quiz.hidePage(this.quiz.pages.length - 1);
        }
    },
    goToQuestion: function (i) {
        var that = this;
        this.position = i,
        setTimeout(function () { that.quiz.showPage(i, that.eval_mode); }, 90);
        this.quiz.hidePage(this.quiz.pages.length - 1);
    },
    evaluate: function () {
        this.eval_mode = true;
        this.position = -1;
        this.quiz.lockAllPages();
        this.evaluator.evaluate(this.quiz);
        this.quiz.pages[this.quiz.pages.length - 1].init(this.evaluator.getResultList());
        this.next();
    },
    resume: function () {
        this.quiz.resume();
    },
    end: function (x) {
        this.running = false;
        this.position = -1,
        this.quiz = {};
        this.max_points = 0,
        this.eval_mode = false;
        this.evaluator = {};
        if (!x) {
            var params = {};
            if(!this.main)params.courseid = this.courseId;
            params.tablet_support = "l2p.quiz";
            rwthapp.navigator.gotoPage('l2p.quizOverview',params,false);
        }
    },
    getPage: function (i) {
        return this.quiz.pages[i];
    },
    load: function (courseId, id,isMain) {
        this.initCache();
        this.checkConnection();
        this.main = isMain=="true";
        if (this.hasCache(courseId, id) || this.online) {
            this.id = id;
            this.courseId = courseId;
        }
    },
    retrieveData: function () {
        //throw new Error(rwthapp.localization.getLocalizedString("errors.quiz.quizNoQuestions"));
        this.initCache();
        this.checkConnection();
        if (this.online) {
            rwthapp.connection.api.l2p.getQuiz(this.courseId, this.id).then(function (data) {
                if (!data) {
                    throw new Error(rwthapp.localization.getLocalizedString("errors.quiz.quizNoQuestions"));
                } else {
                    Quiz.Mediator.setup(data);
                }

            }).catch(function (e){
                $("#overlayQuiz").hide();
                $("#quizContent").html(rwthapp.templateRenderer.fetch("errorpartial", { message: rwthapp.localization.getLocalizedString("errors.quiz.quizNoQuestions") }));

                // Perform postprocessing (fixing icons, removing waves effect) if necessary
                rwthapp.templateRenderer.performPostprocessing();
            });
        }
        else this.setupFromCache();
    },
    saveCache: function () {
        var storage = new rwthapp.Storage("quiz");
        storage.addAttribute("quizCache");
        storage.setQuizCache(JSON.stringify(this.cache));
    },
    setupFromCache: function () {
        if(this.cache[this.courseId + " " + this.id])this.setup(this.cache[this.courseId + " " + this.id]);
    },
    initCache: function () {
        var storage = new rwthapp.Storage("quiz");
        storage.addAttribute("quizCache");
        this.cache = JSON.parse(storage.getQuizCache()) || {};
    },
    hasCache: function (courseId, id) {
        var x = this.cache[courseId + " " + id];
        return x != undefined;
    },
    checkConnection: function () {
        if (navigator.network) {
            var networkState = navigator.network.connection.type;
            this.online = networkState != Connection.NONE;
        } else {
            this.online = false;
        }
    }
};
