// com.tts.initial.html5.quiz.result.detailed
define( [
	"jquery",
	"./locals",
],
function (
		jq,
		uiText
) {

	"use strict";

	/**
	 * @constructor
	 */
	function ScoreDetailed( context, metadata ) {

		var parameters = metadata.parameters,
			borderWidth = parameters.get( "borderWidth", 1 ),
			isSectionEvaluation = parameters.asBool( "isSectionEvaluation", "0" ),
			alternateColors = parameters.asBool( "alternateColors", "0" ),
			backgroundColor1 = asRgbaValue( "backgroundColor1", "#d8dee3", "backgroundColor1Transparency" ),
			backgroundColor2 = asRgbaValue( "backgroundColor2", "#e2e6ea", "backgroundColor2Transparency" ),
			borderColor = asRgbaValue( "borderColor", "#98a7b5", "borderTransparency" ),
			borderStyle = parameters.get( "borderStyle", "horizontal" ),
			imageCorrect = parameters.get( "iconCorrect", null ),
			iconImageCorrect = imageCorrect ? context.stage.getSharedPath() + imageCorrect.fileName : context.getPath() + "correct.png",
			imageWrong = parameters.get( "iconWrong", null ),
			iconImageWrong = imageWrong ? context.stage.getSharedPath() + imageWrong.fileName : context.getPath() + "wrong.png",
			imageBack = parameters.get( "iconBack", null ),
			iconImageBack = imageBack ? context.stage.getSharedPath() + imageBack.fileName : context.getPath() + "back_to_question.png",
			showBackIcon = parameters.asBool( "showBackIcon", "0" ),
			pointerUpEventName,
			col1Css = { "text-align": "right", "padding-right": "5px", "width": parameters.get( "widthCol1", 30 ) },
			col3Css = { "text-align": "center", "padding": "0 5px", "width": parameters.get( "widthCol3", 100 ) },
			col4Css = { "text-align": "right", "width": "1px" },
			col5Css = { "text-align": "right", "width": "1px" },
			currentPage = metadata.page,
			scoringSections = [],
			allPages = getPages(),
			aQuestions = context.quiz.getQuestions(),
			isTouchDevice = ( 'ontouchstart' in window ) || ( navigator.MaxTouchPoints > 0 ) || ( navigator.msMaxTouchPoints > 0 ) || context.device.isMobile(),
			backToTestQuestionCaption = uiText.get( "player.quiz.result.back_to_test_question", metadata.stage.getContentLanguage() );

		function getPages(){

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

			return metadata.stage.getMainPath().getPages();
		}

		function asRgbaValue( colorParameterName, defaultColor, transparencyParameterName ) {
			var color = hexToRgb( parameters.get(colorParameterName, defaultColor)),
				alpha = asAlpha( parameters.asNumber(transparencyParameterName, 0) );
			return "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + alpha + ")";
		}

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

		function asAlpha( percentValue ) {
			return (100 - percentValue) / 100;
		}

		function getFontStyle( paramValue ) {
			switch ( paramValue ) {
				case 2:
					return "\"Times New Roman\", Times, serif";
				case 3:
					return "Verdana, Geneva, sans-serif";
				case 4:
					return "\"Courier New\", Courier, monospace";
				default:
					return "Arial, Helvetica, sans-serif";
			}
		}

		function createView() {
			var shellElement = jq(context.getElement())
				.css({
					"font-family": getFontStyle( metadata.parameters.asNumber( "font-family", "1" ) ),
					"font-size": metadata.parameters.asNumber( "font-size", "12" ),
					"color": metadata.parameters.get( "text-color", "#000000" ),
					"font-weight": "normal"
				});

			shellElement.append(createResultTable());
			if (context.stage.isInAuthoringMode()) {
				createAuthoringShield( shellElement );
			}
		}

		function refreshView() {
			jq( context.getElement() ).children( ".scOverflow" ).remove();
			jq( context.getElement() ).append( createResultTable() );
		}

		function createResultTable() {
			var resultTable = jq(document.createElement("table"))
				.css({
					"width": "100%",
					"border-spacing": "0",
					"border-collapse": "collapse",
					"border-top": borderWidth + "px solid " + borderColor
				})
                .addClass("DetailedResultTable");

			if (borderStyle !== "horizontal") {
				resultTable.css({
					"border-right": borderWidth + "px solid " + borderColor,
					"border-left": borderWidth + "px solid " + borderColor
				});
			}

			resultTable.append(createResultTableBody());

			return createScrollWrapper( resultTable );
		}

		function createScrollWrapper( table ) {

			var overflowWrapper = jq( document.createElement("div") );
			overflowWrapper.css( {
				"position" : "absolute",
				"width" : "100%",
				"height" : "100%",
				"overflow-x" : "visible",
				"overflow-y" : "auto"
			});
			overflowWrapper.addClass( "scOverflow" );
			overflowWrapper.append(table);

			if( isTouchDevice ){
				addTouchScroll( overflowWrapper );
			}

			return overflowWrapper;
		}

		function addTouchScroll( jqElement ) {

			var scrollStartPos = 0,
				positionData;

			jqElement.on( "touchstart", function (event) {
				positionData = getPointerPositionFromEvent( event );

				if( jqElement.get(0).scrollHeight > jqElement.height() ) {
					lockNavigation();
				}

				scrollStartPos = this.scrollTop + positionData.pageY;
				event.preventDefault();
			});

			jqElement.on( "touchmove", function (event) {
				positionData = getPointerPositionFromEvent( event );
				this.scrollTop = scrollStartPos - positionData.pageY;
				event.preventDefault();
			});

			jqElement.on( "touchend", function (event) {
				unlockNavigation();
				event.preventDefault();
			});
		}

		function getPointerPositionFromEvent( event ){

			if( event.originalEvent ) {

				if( event.originalEvent.touches && event.originalEvent.touches[0] ){
					return event.originalEvent.touches[0];
				}

				if( event.originalEvent.changedTouches && event.originalEvent.changedTouches[0] ){
					return event.originalEvent.changedTouches[0];
				}
			}

			return event;
		}

		function lockNavigation() {
			if( context.stage.trigger && typeof( context.stage.trigger.lock ) === "function" ) {
				context.stage.trigger.lock(metadata.getId());
			}
		}

		function unlockNavigation() {
			if( context.stage.trigger && typeof( context.stage.trigger.unlock ) === "function" ) {
				context.stage.trigger.unlock(metadata.getId());
			}
		}

		function createResultTableBody() {
			var tBody = jq(document.createElement("tbody")),
				rows = getResultTableRows();

			rows.forEach(function(row) {
				tBody.append(row);
			});

			return tBody;
		}

		function getResultTableRows() {
			if (context.stage.isInAuthoringMode()) {
				return getAuthoringTableRows();
			}

			return getTableRows();
		}

		function getAuthoringTableRows() {
			var tableRows = [],
				authoringTable = {
					rows: [
						// row1
						{
							id: "quizRow_0",
							backgroundColor: backgroundColor1,
							cells: [
								{ type: "text", value: "1", css: col1Css},
								{ type: "text", value: "Quiz 1"},
								{ type: "text", value: "5 / 5", css: col3Css},
								{ type: "image", value: iconImageCorrect, css: col4Css }
							]
						},
						// row2
						{
							id: "quizRow_1",
							backgroundColor: alternateColors? backgroundColor2 : backgroundColor1,
							cells: [
								{ type: "text", value: "2", css: col1Css },
								{ type: "text", value: "Quiz 2" },
								{ type: "text", value: "0 / 5", css: col3Css },
								{ type: "image", value: iconImageWrong, css: col4Css }
							]
						}
					]
				};

			authoringTable.rows.forEach(function(row) {
				tableRows.push(createTableRow(row));
			});

			return tableRows;
		}

		function getQuestion(page){
			for (var i=0; i < aQuestions.length; i++) {
				if (page.getId() === aQuestions[i].getPageMetadata().getId()) {
					return aQuestions[i];
				}
			}
			return null;
		}

		function getTableRows() {
			var rowsCollection = [],
				tableRows = [],
				question,
				questionNumber = 0,
				resultObject,
				backgroundColor,
				relevantPages = getRelevantQuizPages(),
				allQuizPages = allPages.filter(function(page) {
					return getQuestion(page) !== null;
				});

			relevantPages.forEach(function(page) {
				question = getQuestion(page);
				questionNumber++;

				resultObject = getQuestionResultObject(question);
				backgroundColor = (alternateColors && questionNumber%2 === 0)? backgroundColor2 : backgroundColor1;

				rowsCollection.push({
					id: "quizRow_" + questionNumber,
					backgroundColor: backgroundColor,
					cells: [
						{ type: "text", value: allQuizPages.indexOf(page)+1, css: col1Css },
						{ type: "text", value: page.getTitle() },
						{ type: "text", value: resultObject.userScore + " / " + resultObject.maxScore, css: col3Css },
						{ type: "image", value: resultObject.icon, css: col4Css },
						{ type: "imageLink", value: iconImageBack, css: col5Css, targetId: page.getId(), targetPage: page }
					]
				});
			});

			rowsCollection.forEach(function(rowObject) {
				tableRows.push(createTableRow(rowObject));
			});

			return tableRows;
		}

		function getRelevantQuizPages() {
			var startPageIndex = getPreviousSectionPageIndex() + 1,
				stopPageIndex = allPages.indexOf(currentPage),
				allRelevantPages = allPages.slice(startPageIndex, stopPageIndex),
				relevantQuizPages;

			if (!isSectionEvaluation) {
				allRelevantPages = allPages;
			}

			relevantQuizPages = allRelevantPages.filter(function(page) {
				return getQuestion(page) !== null;
			});

			return relevantQuizPages;
		}

		function getQuestionResultObject(question) {
			var userScore = parseInt( question.getScore() ),
				maxScore = parseInt( question.getMaxScore() ),
				icon = (userScore > 0 && userScore === maxScore) ? iconImageCorrect : iconImageWrong;

			return {
				userScore : userScore,
				maxScore: maxScore,
				icon : icon
			}
		}

		function getPreviousSectionPageIndex() {
			if (!isSectionEvaluation || scoringSections.length === 0) {
				return -1;
			}

			var lastSectionPageId = -1,
				lastSectionPage,
				id;

			for(id in scoringSections) {
				if (scoringSections.hasOwnProperty(id)) {
					if (scoringSections[id] === currentPage.getId()) {
						break;
					}
					lastSectionPageId = scoringSections[id];
				}
			}

			if( lastSectionPageId === -1 ) {
				return -1;
			}

			lastSectionPage = getPage(lastSectionPageId);
			if (!lastSectionPage) {
				return -1;
			}

			return allPages.indexOf(lastSectionPage);
		}

		function getPage(id) {
			var page = null;

			if (!id) {
				return null;
			}

			for (var p in allPages) {
				if (allPages.hasOwnProperty(p) && allPages[p].getId() === id) {
					return allPages[p];
				}
			}

			return page;
		}

		function createTableRow(rowObject) {
			var row = jq(document.createElement("tr"))
				.attr("id", rowObject.id)
				.css("backgroundColor", rowObject.backgroundColor);

			rowObject.cells.forEach( function ( cellObject ) {
				if ( cellObject.type == "imageLink" && !showBackIcon ) {
					return;
				}
				row.append(createTableCell(cellObject));
			});

			return row;
		}

		function createTableCell(cellObject) {
			var cell = jq(document.createElement("td"))
				.css({
					"-moz-background-clip" : "padding-box",
					"-webkit-background-clip" : "padding-box",
					"background-clip" : "padding-box",
					"border-bottom": borderWidth + "px solid " + borderColor,
					"padding-top": Math.abs( metadata.parameters.asNumber( "padding-top", "0" ) ) + "px",
					"padding-bottom": Math.abs( metadata.parameters.asNumber( "padding-bottom", "0" ) ) + "px"
				});

			if (cellObject.css) {
				cell.css(cellObject.css);
			}

			switch(cellObject.type) {
				case "text":
					cell.text(cellObject.value);
					break;
				case "image":
					cell.append(createImage(cellObject.value));
					break;
				case "imageLink":
					cell.append( createImageLink( cellObject.value, cellObject.targetId, cellObject.targetPage ) );
					break;
				default:
					break;
			}

			return cell;
		}

		function createImage(source) {
			return jq(document.createElement("img")).attr("src", source);
		}

		function createImageLink( source, id, page ) {
			return jq( document.createElement( "img" ) )
				.attr({
					"src": source,
					"title": backToTestQuestionCaption
				} )
				.css( {
					"cursor": "pointer"
                })
				.on( pointerUpEventName, function () {
					if ( context.getPlayerName() == "html5" ) {
						cancelEvent();
						context.stage.navigation.gotoPageById( id );
					} else {
						cancelEvent();
						context.stage.navigation.gotoPage( page );
					}
				});
		}

		function initPointerEventNames() {

			if ( pointerUpEventName ) {
				return;
			}

			if ( context.stage.isInPreviewMode() ) {
				pointerUpEventName = "mouseup";
				return;
			}

			pointerUpEventName = context.device.getUpEvents();
		}

		function cancelEvent( e ) {
			context.device.cancelEvent( e );
		}

		function createAuthoringShield( shellElement ) {
			// create an object shield so we are able to select and drag the element in the editor
			var objShield = jq(document.createElement("div"));
			objShield.css({
				"position" : "absolute",
				"left" : "0px",
				"top" : "0px",
				"background-color" : "#ffffff",
				"opacity" : "0",
				"width" : "100%",
				"height" : "100%",
				"z-index" : "9999"
			});
			objShield.addClass( "scShield" );
			shellElement.append( objShield );
		}

		function getExistingPagesFrom( idArray ) {
            var result = [];

            allPages.forEach( function(page) {
                if ( idArray.indexOf(page.getId()) !== -1) {
                    result.push(page.getId());
                }
            });

            return result;
		}

		// revealing public API
		return {
			onLoading : function() {
				context.page.event.bindOnEnter( this );
				var scoringSectionsJSON = context.stage.variable.get( "tts_scoreSectionId", "tts.scoreDetailed" );
				if (scoringSectionsJSON){
					scoringSections = JSON.parse( scoringSectionsJSON );
				}
				context.stage.variable.set( "tts_scoreSectionId", JSON.stringify( scoringSections ), "tts.scoreDetailed" );
				initPointerEventNames();

				createView();
			},

			onEnterPage : function() {
                var currentPageId = currentPage.getId();

                scoringSections = getExistingPagesFrom( scoringSections );
                if( scoringSections.indexOf(currentPageId) === -1) {
                    scoringSections.push(currentPageId);
				}

				context.stage.variable.set( "evaluationPageId", currentPageId, "tts.scoreDetailed" );
				context.stage.variable.set( "tts_scoreSectionId", JSON.stringify( scoringSections ), "tts.scoreDetailed" );
				refreshView();
			}
		};
	}

	return ScoreDetailed;
});
