// HTML4 / HTML5: No differences
define(["jquery"], function (jq) {
	"use strict";

	/**
	 * @constructor
	 */
	return function (context, metadata) {
		var instance = null,
			isStandardPlayer = context.getPlayerName() === "standard",
			element = null,
			quizStateBasedVisibilty,
			scoreBasedVisibilty,
			testRunBasedVisibilty,
			isVisible = false,
			isAccessibilityMode = metadata.parameters.asBool("accessibility_mode", false),
			textElement,
			text = metadata.parameters.get("text", ""),
			m_testRunRoutineDeactivated = false;

		function createTargetElement(objElement) {
			element = jq(objElement);

			var parameterAsNumber = metadata.parameters.asNumber,
				parameterAsString = metadata.parameters.get,
				parameterAsBool = metadata.parameters.asBool,
				fontSize = parameterAsString("font-size", "14"),
				fontFamily = parameterAsNumber("font-family", "Arial, Helvetica, sans-serif"),
				borderWidth = parameterAsNumber("border-size", "1"),
				borderTransparency = parameterAsNumber("border-transparency", "0"),
				backgroundTransparency = parameterAsNumber("background-transparency", "100"),
				backgroundColor = hexToRgb(parameterAsString("background-color", "#cccccc")),
				borderColor = hexToRgb(parameterAsString("border-color", "#98a7b5")),
				authoringView;

			quizStateBasedVisibilty = parameterAsNumber("quiz_state_based_visibilty", "0");
			scoreBasedVisibilty = parameterAsNumber("score_based_visibilty", "0");
			testRunBasedVisibilty = parameterAsNumber("test_run_based_visibilty", "0");

			textElement = jq(document.createElement("div"))
				.css( {
					"position": "absolute",
					"width": "100%",
					"height": "100%",
					"background-color": "rgba(" + backgroundColor.r + ", " + backgroundColor.g + ", " + backgroundColor.b + ", " + ((100 - backgroundTransparency) / 100) + ")",
					"font-family": getFontFamilyString(fontFamily),
					"font-size": fontSize + "px",
					"font-weight": (parameterAsBool("bold", true)) ? "bold" : "normal",
					"font-style": (parameterAsBool("italic", false)) ? "italic" : "normal",
					"color": parameterAsString("color", "#919191"),
					"line-height": fontSize + "px",
					"padding-left": (parameterAsNumber("padding-left", "15") - borderWidth) + "px",
					"padding-right": (parameterAsNumber("padding-right", "15") - borderWidth) + "px",
					"padding-top": (parameterAsNumber("padding-top", "15") - borderWidth) + "px",
					"text-align": parameterAsString("text_orientation", "center"),
					"box-sizing": "border-box"
				});

			if (borderWidth !== 0) {
				textElement.css("border", borderWidth + "px solid rgba(" + borderColor.r + ", " + borderColor.g + ", " + borderColor.b + ", " + ((100 - borderTransparency) / 100) + ")");
			}

			if (isAccessibilityMode) {
				textElement.attr({
					"aria-live": "polite",
					"aria-atomic": "true"
				})
			} else {
				textElement.html(text);
			}

			element.append(textElement);

			if (context.stage.isInAuthoringMode()) {
				textElement.html(text);
				authoringView = jq(document.createElement("div"));
				authoringView.css({
					"width": "100%",
					"height": "100%",
					"position": "absolute",
					"opacity": "0.15"
				});
				if (backgroundTransparency === 100) {
					authoringView.css({
						"background-image": "url(\"" + context.getPath() + "invis.png\")"
					});
				}
				element.prepend(authoringView);
			}
		}

		function getFontFamilyString(fontFamily) {
			switch (parseInt(fontFamily)) {
				case 2:
					return "'Times New Roman', Times, serif";
				case 3:
					return "Verdana, Geneva, sans-serif";
				case 4:
					return "'Courier New', Courier, monospace";
				case 1:
				default:
			}
			return "Arial, Helvetica, sans-serif";
		}

		function hideElement() {
			if (isAccessibilityMode) {
				element.css({ "opacity": "0" });
				textElement.html("");
			} else {
				element.hide();
			}

			var arrayElementIDs = element.attr("id").split("I").filter(Boolean);
			if (arrayElementIDs.length > 0) {
				if (isAccessibilityMode) {
					jq("#I" + arrayElementIDs[0]).children().css({ "opacity": "0" });
				} else {
					jq("#I" + arrayElementIDs[0]).children().hide();
				}
			}

            context.page.event.trigger( instance,  "onHide" );
            isVisible = false;
		}

		function showElement() {

			if (isAccessibilityMode) {
				element.css({ "opacity": "1" });
				textElement.html(text);
			} else {
				element.show();
			}

			var arrayElementIDs = element.attr("id").split("I").filter(Boolean);
			if (arrayElementIDs.length > 0) {
				if (isAccessibilityMode) {
					jq("#I" + arrayElementIDs[0]).children().css({ "opacity": "1" });
				}
				else {
					jq("#I" + arrayElementIDs[0]).children().filter(function(i) {
						return !(this instanceof HTMLScriptElement);
					}).show();
				}
			}

            context.page.event.trigger( instance, "onShow" );
            isVisible = true;
		}

		function hexToRgb(hex) {
			var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
			return result ? {
				r: parseInt(result[1], 16),
				g: parseInt(result[2], 16),
				b: parseInt(result[3], 16)
			} : {
				r: 0,
				g: 0,
				b: 0
			};
		}

		function showInTestRun() {
			return quizStateBasedVisibilty === 0;
		}

		function showInBestSolution() {
			return quizStateBasedVisibilty === 1 || quizStateBasedVisibilty === 3;
		}

		function showInUserSolution() {
			return quizStateBasedVisibilty === 2 || quizStateBasedVisibilty === 3;
		}

		function canBeDisplayed(evaluationStatus) {

			if (["correct", "partially_correct", "failed"].indexOf(evaluationStatus) === -1) {
				return false;
			}

			switch (scoreBasedVisibilty) {
				case 0:
					return true;
				case 1:
					return evaluationStatus === "correct";
				case 2:
				case 3:
					return evaluationStatus === "failed" || evaluationStatus === "partially_correct";
				default:
                    return false;
			}
		}

		function canBeDisplayedInRun(numberOfRun) {
			return testRunBasedVisibilty === 0 || testRunBasedVisibilty === parseInt(numberOfRun);
		}

		function getEvaluationStatus() {
			var questionMetadata = getQuestionMetadata();
			if (questionMetadata === null) {
				return null;
			}
			return questionMetadata.getStatus();
		}

		function getQuestionMetadata() {
			var questionMetadata = null,
				questions = context.quiz.getQuestions(),
				i = 0,
				question,
				numberOfQuestions = questions.length;
			for (; i < numberOfQuestions; i++) {
				question = questions[i];
				if (question.getPageMetadata().getId() === metadata.page.getId()) {
					questionMetadata = question;
					break;
				}
			}
			return questionMetadata;
		}

		// revealing public API
		return {
			onLoading: function () {
                instance = this;
				createTargetElement(context.getElement());
				//if (!context.stage.isInAuthoringMode()) {
				//	hideElement();
				//}
				var quizPageEvent = context.page.quiz.event;

				context.page.event.bindOnEnter(instance);
				quizPageEvent.bindOnEvaluateTestRun(instance);
				quizPageEvent.bindOnUserSolution(instance);
				quizPageEvent.bindOnBestPracticeSolution(instance);
				context.page.event.bind(instance, "onNoAnswerGiven");
			},

			onEnterPage: function () {

				if (context.stage.isInAuthoringMode()) {
                    return;
                }

				if( isStandardPlayer ){
                    hideElement();
                    m_testRunRoutineDeactivated = false;
				}
				else {
                    isVisible ? showElement() : hideElement();
                }
			},

			onEvaluateTestRun: function () {
				if (!isStandardPlayer && quizStateBasedVisibilty === 4) {
					hideElement();
				}

				var params = arguments.length > 1 ? arguments[1] : (arguments.length > 0 ? arguments[0] : {}),
					evaluationStatus;

				// in some cases evaluateTestRun and onUserSolution is fired at the same time and if onUserSolution is executed first, the
				// evaluateTestrun routine will overwirte the userSolution results. So this is a workaround.
				if (m_testRunRoutineDeactivated) {
					return;
				}

				evaluationStatus = getEvaluationStatus();
				if(evaluationStatus === null) {
					return;
				}

				showInTestRun() &&
				canBeDisplayedInRun(params.currentTestRun) &&
				canBeDisplayed(evaluationStatus) ?
					showElement() :
					hideElement();
			},

			onUserSolution: function () {
				if (!isStandardPlayer && quizStateBasedVisibilty === 4) {
					hideElement();
				}

				// in some cases evaluateTestRun and onUserSolution is fired at the same time and if onUserSolution is executed first, the
				// evaluateTestrun routine will overwirte the userSolution results. So this is a workaround.
				m_testRunRoutineDeactivated = true;

				var evaluationStatus = getEvaluationStatus();
				if(evaluationStatus === null) {
					return;
				}

				showInBestSolution() &&
				canBeDisplayed(evaluationStatus) ?
					showElement() :
					hideElement();
			},

			onBestPracticeSolution: function () {
				if (!isStandardPlayer && quizStateBasedVisibilty === 4) {
					hideElement();
				}

				var evaluationStatus = getEvaluationStatus();
				if(evaluationStatus === null) {
					return;
				}

				showInUserSolution() &&
				canBeDisplayed(evaluationStatus) ? showElement() : hideElement();
			},

			onNoAnswerGiven: function () {
				if (!isStandardPlayer && quizStateBasedVisibilty === 4) {
					showElement();
				}
			}
		};
	};
});
