/**
 * @author Sebastian Felling for Felling Softwareentwicklung, Germany
 * www.felling-software.com
 * v1.0.0.6 as of 2009-07-28
 * 
 * To be fixed
 * => IE6-8: cursor/focus issues
 */

var intStep = -1;
var bolWait = false;
var XMLDoc;
var vpUnits = new Array();
var vpArticles = new Array();
var intSelectedUnitID = -1;
var queueUnits = new Array();
var queue = new Array();
var selectedExTypes = new Array();			// array that holds all type IDs of the user selected exercise types
var intCurrentQueueUnitIndex = -1;
var currentArticle;
var currentEx;
var settings = new Array();					// saves user settings

// CLASSES
function vpUnitStats(intCountWords, intCountFIBs, intCountMatchings, intCountMCs, intCountQuizzes) {
	this.intCountWords = intCountWords;
	this.intCountFIBs = intCountFIBs;
	this.intCountMatchings = intCountMatchings;
	this.intCountMCs = intCountMCs;
	this.intCountQuizzes = intCountQuizzes;
	this.intCountAll = intCountWords + intCountFIBs + intCountMatchings + intCountMCs + intCountQuizzes;
}

function vpUnit(id, name, description) {
	this.id = id;
	this.name = name;
	this.description = description;
	this.unitStats = GetUnitStats(id);
}

function vpArticle(id, description, sourceLangCode, targetLangCode, authorName, type, sources, unitidfingerprint, exID) {
	this.id = id;
	this.description = description;
	this.sourceLangCode = sourceLangCode;
	this.targetLangCode = targetLangCode;
	this.authorName = authorName;
	this.type = parseInt(type);				// 0 word, 1 fib, 2 fc, 3 matching, 4 mc, 5 quiz
	this.source = sources;
	this.unitIDFingerPrint = unitidfingerprint;
	this.exID = exID;
}

function queueUnit(articleID, articleIndex) {
	this.articleID = articleID;
	this.articleIndex = articleIndex;
	this.fail = false;
	this.pass = false;
	this.processed = false;
}

function exWordTargetSynonym(strTarget, strIPA, intSoundFileID, strExample) {
	this.strTarget = strTarget;
	this.strIPA = strIPA;
	this.intSoundFileID = intSoundFileID;
	this.strExample = strExample;
}

function exWord(strSource, exWordTargets) {
	this.strSource = strSource;
	this.exWordTargets = exWordTargets;
}

function exFIBsBlank(strAnswers, strHint, strRemarkAfter, intAudioID) {
	var strSavedAnswers = new Array();
	
	// remove empty answers
	for(var i = 0; i < strAnswers.length; i++) {
		if(strAnswers[i].length > 0) {
			strSavedAnswers.push(strAnswers[i]);
		}
	}
	
	this.strAnswers = strSavedAnswers;
	this.strHint = strHint;
	this.strRemarkAfter = strRemarkAfter;
	this.intAudioID = intAudioID;	
}

function exFIBs(strTranslatedText, blanks, bolEvenWidth, bolDragDropEx, intMinPoints) {
	this.strTranslatedText = strTranslatedText;
	this.blanks = blanks;
	this.bolEvenWidth = (typeof bolEvenWidth == 'string') ? bolEvenWidth.toLowerCase() == 'true' : bolEvenWidth;
	this.bolDragDropEx = (typeof bolDragDropEx == 'string') ? bolDragDropEx.toLowerCase() == 'true' : bolDragDropEx;
	this.intMinPoints = intMinPoints;
}

// prepare document for first start
function clear() {
	// hide javascript enabled warning
	elementShow('javawarning', false);
	
	// round corners
	$('.rounded').corners();
}

// hide/show DOM element
function elementShow(elementID, bolShow, displayMode) {
	if($('#' + elementID).length > 0) {
		if(!bolShow) {
			$('#' + elementID).fadeOut('slow');
			document.getElementById(elementID).style.visibility = 'hidden';
			document.getElementById(elementID).style.display = 'none';
		} else {
			$('#' + elementID).fadeIn('slow');
			document.getElementById(elementID).style.visibility = 'visible';
			document.getElementById(elementID).style.display = displayMode;
		}
	}
}

function elementHideNoFancy(elementID) {
	document.getElementById(elementID).style.visibility = 'hidden';
	document.getElementById(elementID).style.display = 'none';
}

// hide/show DOM element value
function elementValueChange(elementID, txtValue) {
	if(document.getElementById(elementID)) {
		document.getElementById(elementID).value = txtValue;
	}
}

// user pressed 'start' button
function startUnit() {
	switch(intStep) {
		case -1:
			// load xml data
			// show "loading" message
			$('#loading').fadeIn('slow');
			elementShow('loading', true, 'block');
			
			// read file param
			var strFile = getURLParam('file');
			
			// check file name integrity
			if(!stringStartsWith(strFile, 'data/')) {
				alert('Du hast eine falsche Datei angegeben.');
				return;
			} else if (!stringEndsWith(strFile, '.xml')) {
				strFile = strFile + ".xml";
			}
			
			// load data xml
			$(document).ready(function(){
				$.ajax({
					type: "GET",
					url: strFile,
					dataType: "xml",
					success: loadXML
				});
			});
			
			// change button start value
			elementValueChange('start', 'Ausgewählte Lektion starten...');

			intStep = 99;		// set to 99: hold further proceedings until processing is done
			break;
			
		case 0:
			var strIntMax = document.getElementById('maxCount').value;
			var intMax = 0;
			
			// unit selected?
			if (intSelectedUnitID == -1) {
				alert('Du musst zuerst eine Lektion auswählen!');
				return;
			} else if(strIntMax.length == 0 || isNaN(strIntMax) || parseInt(strIntMax) < 1 || parseInt(strIntMax) > 100) {
				alert('Anzahl der Übungen: Du musst eine gültige Zahl (von 1 bis 100) eingeben.')
			} else {
				// hide unit selection
				elementShow('units', false);
				
				// read settings
				settings['englishToOptional'] = document.getElementById('optEnglishToOptional').checked;
				settings['bracketsOptional'] = document.getElementById('optBracketsOptional').checked;
				intMax = parseInt(strIntMax);
				
				// show unit title
				document.getElementById('unittitle').innerHTML = vpUnits[unitsGetIndexByID(intSelectedUnitID)].name;
				$('#title').fadeIn('slow');
				elementShow('title', true, 'block');

				// read settings
				// which exercise types selected?
				var typeOptions = document.getElementById('config_types').getElementsByTagName('input');
				for(var i = 0; i < typeOptions.length; i++) {
					// option checked? => add to selected ex types
					if(typeOptions[i].checked) {
						selectedExTypes.push(parseInt(typeOptions[i].value));
					}
				}
				
				// create queue units
				for(var i = 0; i < vpArticles.length; i++) {
					var strSelectedUnitPrint = '<' + intSelectedUnitID + '>';
					
					// article is associated with selected unit?
					if(vpArticles[i].unitIDFingerPrint.indexOf(strSelectedUnitPrint) != -1) {
						// article is of checked ex type?
						if(selectedExTypes.indexOf(vpArticles[i].type) != -1) {
							// add to queue units
							var newQueueUnit = new queueUnit(vpArticles[i].id, i);
							queueUnits.push(newQueueUnit);
						}
					}
				}
				
				// queue length exceeds intMax?
				if(queueUnits.length >= intMax) {
					// randomly delete elements to reach intMax
					var intIterations = queueUnits.length - intMax;
					
					for(var i = 0; i < intIterations; i++) {
						var intRandom = Math.floor(Math.random() * queueUnits.length)
						queueUnits.splice(intRandom, 1);
					}
				}
				
				// create queue
				for(var i = 0; i < queueUnits.length; i++) {
					queue.push(i);	
				}
				
				// shuffle queue
				arrayShuffle(queue);
				
				// hide start button
				elementShow('start', false);
				
				// set button values and show buttons
				elementShow('restart', true, 'inline');
				elementShow('status', true, 'inline');
				elementShow('next', true, 'inline');
	
				// get first unit from queue
				queueShift();
				break;	
			}
			break;	
	}
}

function queueShift() {
	// reset wait
	bolWait = false;
	
	// change button value
	elementValueChange('next', "Antwort prüfen >>");
	
	// hide infoBox
	$('#infoBox').fadeOut('slow');
	
	// queue empty?
	if(queue.length==0) {
		queueEnd();
		return;
	} else {
		// queue not empty => process
		intCurrentQueueUnitIndex = queue.shift();

		// set current article
		currentArticle = vpArticles[queueUnits[intCurrentQueueUnitIndex].articleIndex];

		// set queue unit to processed
		queueUnits[intCurrentQueueUnitIndex].processed = true;
		
		// hide all items
		clearPanels();
		
		// which article type?
		switch(currentArticle.type) {
			case 0:		// word
				loadExWord();
				
				// set focus
				$("#itmWord input:first").focus(); 
				
				break;
			case 1:		// FIBs
				loadExFIBs();
				
				// set focus
				$("#itmFIB input:first").focus(); 
				
				break;
			case 2:		// flash card
			
				break;
			case 3:		// matching
			
				break;
			case 4:		// MC
		
				break;
			case 5:		// quiz
				
				break;
		}
		
		// print status
		if(queue.length == 0) {
			elementValueChange('status', 'Letzte Übung!');
		} else {
			elementValueChange('status', 'Noch ' + queue.length + ' Übungen');
		}
	}
}

function queueEnd() {
	// hide panel
	elementShow('panel', false);
	elementShow('adPanel', true, 'block');
}

function getLanguageNameByCode(strLangCode) {
	switch(strLangCode){
		case 'eng':
			return 'Englisch';
			break;
		case 'deu':
			return 'Deutsch';
			break;
		default:
			return strLangCode;
			break;
	}	
}

function loadExWord() {
	// load word from article base
	var intWordID = currentArticle.exID;

	$(XMLDoc).find('word').each(function() {
		// find id
		if($(this).attr('id') == intWordID) {
			var strWordSource = $(this).children('sourcesynonym').text();
			var targetSynonyms = new Array();
			
			// get all target synonyms
			$(this).children('targetsynonyms').find('synonym').each(function() {
				// read target synonym properties
				var strWordTarget = $(this).text();
				var strIPA = $(this).attr('ipaword');
				var intSoundFileID = $(this).attr('soundfileid');
				var strExample = $(this).attr('examplesentence');
				
				// create and add new target synonym
				var newTargetSynonym = new exWordTargetSynonym(strWordTarget, strIPA, intSoundFileID, strExample);
				targetSynonyms.push(newTargetSynonym);
			});
			
			// create new word
			var newExWord = new exWord(strWordSource, targetSynonyms);
			currentEx = newExWord;
		}
	});
	
	// hide keys
	elementShow('itmWordKeys', false);
	
	// load source synonym
	document.getElementById('itmWord').getElementsByTagName('strong')[0].innerHTML = getLanguageNameByCode(currentArticle.targetLangCode);
	document.getElementById('sourceSynonym').innerHTML = currentEx.strSource;
	
	// load input boxes
	for(var i = 0; i < 5; i++) {
		var strInputID = 'itmWordInput' + i;
		
		// reset input box
		document.getElementById(strInputID).className= "word";
		document.getElementById(strInputID).value = '';
		
		// show/hide boxes
		if(i < currentEx.exWordTargets.length) {
			elementShow(strInputID, true, 'inline');
		} else {
			elementShow(strInputID, false);
		}
	}
	
	// show item panel
	elementShow('itmWord', true, 'block');
	
	// set focus to first input box
	document.getElementById('itmWordInput0').focus();
}

function loadExFIBs() {
	// load FIBs from article base
	var intFIBsID = currentArticle.exID;
	
	$(XMLDoc).find('fillintheblanks').each(function() {
		// find ID
		if($(this).attr('id') == intFIBsID) {
			var strTranslatedText = $(this).children('translatedtext').text();
			var blanks = loadFIBsRetranslateText(strTranslatedText);
			var bolEvenWidth = $(this).attr('evenwidth');
			var bolDragDropEx = $(this).attr('dragdropexercise');
			var intMinPoints =  parseInt($(this).attr('minimumpoints'));
			
			// parse text
			var strHTML = '';
			var strParts = strTranslatedText.split('{');
			
			// iterate through parts
			var intCurrentBlankIndex = -1;
			
			for(var i = 0; i < strParts.length; i++) {
				if(strParts[i].indexOf('}') == -1) {
					// pre-text
					strHTML = strHTML.concat(strParts[i]);
				} else {
					// blank
					intCurrentBlankIndex++;
					var strInnerParts = strParts[i].split('}');
					
					// add input with answer and remarksAfter info
					//var strInputBox = '<input class="fib" id="fibsInput' + intCurrentBlankIndex + '" onkeyup="itmFIBsInput_keyUp(event, this.id)" /><a class="fibInfo" href="#" id="fibInfo' + intCurrentBlankIndex + '">?<span class="fibInfo">Erwartete Antwort(en):<ul><li>' + blanks[intCurrentBlankIndex].strAnswers.join('</li><li>') + '</li></ul>' + blanks[intCurrentBlankIndex].strRemarkAfter + '</span></a>';
					var strInputBox = '<input class="fib" id="fibsInput' + intCurrentBlankIndex + '" onkeyup="itmFIBsInput_keyUp(event, this.id)" /><a class="fibInfo" href="#" id="fibInfo' + intCurrentBlankIndex + '">&nbsp;&nbsp;&nbsp;<span class="fibInfo">Erwartete Antwort(en):<br /><span class="fibKeys">' + blanks[intCurrentBlankIndex].strAnswers.join('<br />') + '</span><br /><br />' + blanks[intCurrentBlankIndex].strRemarkAfter + '</span></a>';
					var strHint = blanks[intCurrentBlankIndex].strHint.length > 0 ? ' [' + blanks[intCurrentBlankIndex].strHint + '] ' : '';				
					strHTML = strHTML.concat(strInputBox).concat(strHint).concat(strInnerParts[1]);
				}
			}
			
			// replace crlf
			strHTML = strHTML.replace(/\f/g, "");
			strHTML = strHTML.replace(/\n/g, "<br />");

			// insert HTML
			document.getElementById('fibtext').innerHTML = '<p>' + strHTML + '</p>';
			
			// load target lang
			document.getElementById('itmFIB').getElementsByTagName('strong')[0].innerHTML = getLanguageNameByCode(currentArticle.targetLangCode);

			// create exFIB
			currentEx = new exFIBs(strTranslatedText, blanks, bolEvenWidth, bolDragDropEx, intMinPoints);
			
			// load drag drop blocks
			if(currentEx.bolDragDropEx) {
				$('#FIBblocks').removeClass('hidden');
				document.getElementById('itmFIB').getElementsByTagName('strong')[1].innerHTML = 'Gib die richtigen Antworten ein. Verwende dabei nur die angezeigten Elemente!';
				loadExFIBsLoadBlocks();
			} else {
				$('#FIBblocks').addClass('hidden');
				document.getElementById('itmFIB').getElementsByTagName('strong')[1].innerHTML = 'Gib die richtigen Antworten ein!';
			}
			
			// show item panel
			elementShow('itmFIB', true, 'block');
		}
	});
}

// load drag drop ex blocks
function loadExFIBsLoadBlocks() {
	var strBlocksHTML = '';
	var strAllBlanks = new Array();
	
	// iterate through blanks: collect all
	for(var i = 0; i < currentEx.blanks.length; i++) {
		strAllBlanks.push(currentEx.blanks[i].strAnswers[0]);
	}
	
	// shuffle array
	arrayShuffle(strAllBlanks);
	
	// create HTML
	for(var i = 0; i < strAllBlanks.length; i++) {
		var strBlock = '<span class="FIBblock">' + strAllBlanks[i] + '</span>';	
		strBlocksHTML = strBlocksHTML.concat(strBlock);
	}
	
	// insert HTML
	document.getElementById('FIBblocks').innerHTML = strBlocksHTML;
}

// retranslate text to retrieve blanks
function loadFIBsRetranslateText(strTranslatedText) {
	var FIBblanks = new Array();
	
	// split text
	var strParts = strTranslatedText.split('{');
	
	// iterate through parts
	for(var i = 0; i < strParts.length; i++) {
		if(strParts[i].indexOf('}') != -1) {
			// get inner parts
			var strInnerParts = strParts[i].split('}');
			
			// get props
			var strProps = strInnerParts[0].split('#');
			
			var strAnswers = new Array();
			strAnswers.push(strProps[0]);
			strAnswers = strAnswers.concat(strProps[1].split('*'));
			
			var strHint = strProps[2];
			var strRemarkAfter = strProps[3];
			var intAudioID = parseInt(strProps[4]);
			
			// create blank
			var newBlank = new exFIBsBlank(strAnswers, strHint, strRemarkAfter, intAudioID);
			FIBblanks.push(newBlank);
		}
	}
	
	// return blanks
	return FIBblanks;
}

function clearPanels() {
	// reset panels
	// reset word panel
	// reset input
	$('input').each(function() {
		$(this).removeClass('correct');
		$(this).removeClass('wrong');
		$(this).removeAttr("disabled");
	});
	
	// hide remarks
	$('div#itmWordInputs span').each(function() {
		$(this).hide();	
	});
	
	// reset keys
	$('#itmWordKeys').hide();
	
	// hide all item panels
	elementHideNoFancy('itmWord', false);
	elementHideNoFancy('itmFIB', false);
	elementHideNoFancy('itmMatching', false);
	elementHideNoFancy('itmQuiz', false);
	elementHideNoFancy('itmMC', false);
}

function checkAndNext() {
	if(!bolWait) {
		// set wait
		bolWait = true;
		
		// check input
		checkInput();
	
		// change button value
		elementValueChange('next', 'Weiter >>');
		$('#next').focus();
		
		// set focus on next button
		
		// proceed when user presses 'next' button
	} else {
		// update stats
		statsUpdate();
		
		// proceed
		queueShift();
	}
}

function statsUpdate() {
	// count stats
	var intCountAll = 0;
	var intCountFirstTryPass = 0;
	var intCountLaterTryPass = 0;
	var intFail = 0;
	
	// iterate through queue items
	for(var i = 0; i < queueUnits.length; i++) {
		if(queueUnits[i].processed) {
			intCountAll++;
			
			// previous fail?
			if(queueUnits[i].pass && (!queueUnits[i].fail)) {
				// passed first try
				intCountFirstTryPass++;
			} else if (queueUnits[i].pass && queueUnits[i].fail) {
				// passed later try
				intCountLaterTryPass++;
			} else {
				// complete fail
				intFail++;
			}
		}
	}
	
	// computer percentages
	intPercentageFirstTryPass = Math.floor(intCountFirstTryPass / intCountAll * 100);
	intPercentageLaterTryPass = Math.floor(intCountLaterTryPass / intCountAll * 100);
	intPercentageFail = Math.floor(intFail / intCountAll * 100);
	
	// update stats
	$('#studyStats li.total_all span.count').html(intCountAll);
	$('#studyStats li.total_pass span.count').html(intCountFirstTryPass + ' (' + intPercentageFirstTryPass + '%)');
	$('#studyStats li.total_pass2 span.count').html(intCountLaterTryPass + ' (' + intPercentageLaterTryPass + '%)');
	
	// show panel
	$('#itmStats').fadeIn('slow');
	elementShow('itmStats', true, 'block');
}

function checkInput() {
	var bolPass = false;
	
	// which article type?
	switch(currentArticle.type) {
		case 0:		// word
			bolPass = checkInputWord();
			break;
		case 1:		// FIBs
			bolPass = checkInputFIBs();
			break;
		case 2:		// flash card
		
			break;
		case 3:		// matching
		
			break;
		case 4:		// MC
	
			break;
		case 5:		// quiz
			
			break;
	}
	
	var strMessage = '';
	
	// pass?
	if(bolPass) {
		// pass!
		// previous fail?
		if(queueUnits[intCurrentQueueUnitIndex].fail) {
			strMessage = "Jetzt bestanden. Toll!";
		} else {
			strMessage = "Bestanden. Sehr gut!";
		}
		
		// set pass
		queueUnits[intCurrentQueueUnitIndex].pass = true;
	} else {
		// fail! = enqueue article
		// previous fail?
		if (queueUnits[intCurrentQueueUnitIndex].fail) {
			strMessage = "Leider wieder durchgefallen. Wird nochmals wiederholt!";
		} else {
			strMessage = "Leider durchgefallen. Wird wiederholt!";
		}
		
		queueUnits[intCurrentQueueUnitIndex].fail = true;
		queue.push(intCurrentQueueUnitIndex);
	}
	
	// show infoBox
	infoBox(bolPass, strMessage);
}

function checkInputWord() {
	var intCorrect = 0;

	// create array of required answers and their derivatives
	var strReqAndDerivatives = new Array(currentEx.exWordTargets.length - 1);
	
	// iterate through all original target words
	for(var i = 0; i < currentEx.exWordTargets.length; i++) {
		var strOriginal = currentEx.exWordTargets[i].strTarget;
		
		// add original
		strReqAndDerivatives[i] = new Array(strOriginal);
		
		// add derivatives of original
		// add 'optional to' derivative
		if (currentArticle.targetLangCode == 'eng' && settings['englishToOptional'] && $.string(strOriginal).startsWith('to ')) {
			var strRemoveTo = strOriginal.replace(/to /, '');
			strReqAndDerivatives[i].push(strRemoveTo);
		}
		
		// add derivatives without square brackets
		// iterate through derivatives of current original
		var strDerivativeWithoutSquareBracketsExp = new Array();
		
		for(var j = 0; j < strReqAndDerivatives[i].length; j++) {
			var strThisDerivative = strReqAndDerivatives[i][j];

			// square brackets available? => add derivative of current derivative without square brackets
			var intBracketOpenedPos = strThisDerivative.indexOf('[');
			var intBracketClosedPos = strThisDerivative.indexOf(']');
			
			if(intBracketClosedPos >= intBracketOpenedPos) {
				strDerivativeWithoutSquareBracketsExp.push(stringTrim(strThisDerivative.replace(/\[.*\]/, '')));
			}
		}
		
		// join arrays
		strReqAndDerivatives[i] = arrayJoin(strReqAndDerivatives[i], strDerivativeWithoutSquareBracketsExp, true);
		
		if (strDerivativeWithoutSquareBracketsExp.length > 0) {
			strReqAndDerivatives[i] = strReqAndDerivatives[i].concat(strDerivativeWithoutSquareBracketsExp);
		}
		
		// add derivatives without round brackets expression
		if(settings['bracketsOptional']) {
			var strDerivativeWithoutRoundBracketsExp = new Array();

			for(var j = 0; j < strReqAndDerivatives[i].length; j++) {
				var strThisDerivative = strReqAndDerivatives[i][j];
				
				// square brackets available? => add derivative of current derivative without square brackets
				var intBracketOpenedPos = strThisDerivative.indexOf('(');
				var intBracketClosedPos = strThisDerivative.indexOf(')');
				
				if(intBracketClosedPos > intBracketOpenedPos) {
					strDerivativeWithoutRoundBracketsExp.push(stringTrim(strThisDerivative.replace(/\(.*\)/, '')));
				}
			}
			
			// join arrays
			strReqAndDerivatives[i] = arrayJoin(strReqAndDerivatives[i], strDerivativeWithoutRoundBracketsExp, true);
		}
		
		// add derivatives without round brackets but with inner expression
		if (settings['bracketsOptional']) {
			var strDerivativeWithoutRoundBrackets = new Array();
			
			for(var j = 0; j < strReqAndDerivatives[i].length; j++) {
				var strThisDerivative = strReqAndDerivatives[i][j];
				
				// square brackets available? => add derivative of current derivative without square brackets
				var intBracketOpenedPos = strThisDerivative.indexOf('(');
				var intBracketClosedPos = strThisDerivative.indexOf(')');
				
				if(intBracketClosedPos > intBracketOpenedPos) {
					strDerivativeWithoutRoundBrackets.push(stringTrim(strThisDerivative.replace(/\(/, '').replace(/\)/, '')));
				}
			}
			
			// join arrays
			strReqAndDerivatives[i] = arrayJoin(strReqAndDerivatives[i], strDerivativeWithoutRoundBrackets, true);
		}
	
		// alert DEBUG INFO
		/*
		var strDerivatives = '';
		for(var intIndex = 0; intIndex < strReqAndDerivatives[i].length; intIndex++) {
			strDerivatives = strDerivatives + '|' + strReqAndDerivatives[i][intIndex] + '|\n';
		}
		
		alert('All derivatives of recent req (' + i + '): ' + strDerivatives);
		*/
	}

	// iterate through given answers
	for(var i = 0; i < currentEx.exWordTargets.length; i++) {
		var strInputName = 'itmWordInput' + i;
		var strInputRemark = 'itmWordRemark' + i;
		var strGiven = document.getElementById(strInputName).value;
		var bolGivenAnswerIsCorrect = false;
		
		// found current given answer in array of requirements and their derivatives?
		// iterate through requirements
		for(var intReq = 0; intReq < strReqAndDerivatives.length; intReq++) {
			var intIndex = strReqAndDerivatives[intReq].indexOf(strGiven);
			
			if(intIndex != -1) {
				//alert('Given answer \'' + strGiven + '\' found at Pos ' + intIndex);
				//alert('Found here: ' + strReqAndDerivatives[intReq][intPos]);
				
				// found => mark as correct
				document.getElementById(strInputName).className = "word correct";
				document.getElementById(strInputRemark).innerHTML = "Korrekt!";
				
				// increment
				intCorrect++;
				
				// delete from required answers
				strReqAndDerivatives.splice(intReq, 1);
				
				// set to true
				bolGivenAnswerIsCorrect = true;
				
				// exit recent loop
				break;
			}
		}
		
		// given answer not correct?
		if(!bolGivenAnswerIsCorrect ) {
			// not found => mark as wrong
			document.getElementById(strInputName).className = "word wrong";
			document.getElementById(strInputRemark).innerHTML = "Antwort falsch oder doppelt!";
		}
			
		// disable input
		document.getElementById(strInputName).disabled = true;
	}
	
	// show all answers + ipa + sound links
	for(var i = 0; i < 5; i++) {
		if(i < currentEx.exWordTargets.length) {
			strElemWordKey = 'itmWordKey' + i;
			strElemWordIPA = 'itmWordIPA' + i;
			strElemExample = 'itmWordExample' + i;
			
			document.getElementById(strElemWordKey).innerHTML = currentEx.exWordTargets[i].strTarget;
			
			// show IPA, if available
			if(currentEx.exWordTargets[i].strIPA.length != 0) {
				document.getElementById(strElemWordIPA).innerHTML = '[' + currentEx.exWordTargets[i].strIPA + ']';
				elementShow(strElemWordIPA, true, 'inline');
			} else {
				elementShow(strElemWordIPA, false);
			}
			
			// show example, if available
			if(currentEx.exWordTargets[i].strExample.length != 0) {
				document.getElementById(strElemExample).innerHTML = 'Beispiel: ' + currentEx.exWordTargets[i].strExample;
				elementShow(strElemExample, true, 'inline');
			} else {
				elementShow(strElemExample, false);
			}
			
			// show list item
			$('#itmWordKeys ul li:nth(' + i + ')').removeClass('hidden');
		} else {
			// hide list item
			$('#itmWordKeys ul li:nth(' + i + ')').addClass('hidden');
		}
	}
	
	// display key panel
	elementShow('itmWordKeys', true, 'block');
	
	// pass?
	if(intCorrect > 0) {
		return true;
	} else {
		return false;
	}
}

function checkInputFIBs() {
	var intCorrect = 0;
	var intWrong = 0;
	
	// collect given answers
	objInputs = document.getElementById('fibtext').getElementsByTagName('input');
	
	// iterate through inputs
	for(var i = 0; i < objInputs.length; i++) {
		if(currentEx.blanks[i].strAnswers.indexOf(objInputs[i].value) != -1) {
			// correct
			intCorrect++;
			objInputs[i].className= 'fib correct';

		} else {
			// wrong
			intWrong++;
			objInputs[i].className= 'fib wrong';
		}
		
		// disable
		objInputs[i].disabled = true;
		
		// show answers and remarkAfter, if available
		var strElement = 'fibInfo' + i;
		$('#' + strElement).fadeIn('slow');
		elementShow(strElement, true, 'inline');
	}
	
	// min points reached?
	var intPercentage = (intCorrect / (intCorrect + intWrong)) * 100;
	return (intPercentage >= currentEx.intMinPoints);
}

function infoBox(bolPass, strMessage) {
	if(bolPass) {
		$('#infoBox').addClass('pass');
		$('#infoBox').removeClass('fail');
	} else {
		$('#infoBox').addClass('fail');
		$('#infoBox').removeClass('pass');
	}
	
	// show message
	document.getElementById('infoBox').innerHTML = '<p>' + strMessage + '<br/>Weiter geht\'s per Klick auf \'Weiter &gt;&gt;\'</p>';
	
	// show infoBox
	$('#infoBox').fadeIn('slow');
	elementShow('infoBox', true, 'block');
}

function loadXML(xml) {
	// save XML
	XMLDoc = xml;

	// find all units
	$(xml).find('unit').each(function(){
		// create and add new unit
		thisUnit = new vpUnit($(this).attr("id"), $(this).attr("path") + ': ' + $(this).attr("name"), $(this).attr("description"));
		vpUnits.push(thisUnit);
	});	
	
	// find all articles
	$(xml).find('article').each(function(){
		// create and add new article
		var exID = -1;
		var articleType = parseInt($(this).attr("type"));

		switch(articleType) {
			case 0:
					// word
					exID = $(this).attr("wordid");
					break;
			case 1:
					// fibs
					exID = $(this).attr("fillintheblanksid");
					break;
			case 2:	// flash card
					exID = $(this).attr("flashcardid");
					break;
			case 3:
					// matching ex
					exID = $(this).attr("matchingexid");
					break;
			case 4:
					// multiple choic ex
					exID = $(this).attr("multiplechoiceexid");
					break;
			case 5:
					// quiz
					exID = $(this).attr("quizid");
					break;
		}
		
		thisArticle = new vpArticle($(this).attr("id"), $(this).attr("description"), $(this).attr("sourcelangcode"), $(this).attr("targetlangcode"), $(this).attr("authorname"), $(this).attr("type"), $(this).attr("sources"), $(this).attr("unitidfingerprint"), exID);
		vpArticles.push(thisArticle);	
	});
	
	// show list of all units
	showUnits();
	
	// proceed
	intStep = 0;
}

// display all units in select
function showUnits() {
	// add all units to selection list
	for(var i = 0; i < vpUnits.length; i++) {
		var thisUnit = vpUnits[i];
		var optn = document.createElement("option");
		optn.text = thisUnit.name + ' (' + thisUnit.unitStats.intCountAll + ' Übungen)';
		optn.value = thisUnit.id;
		document.getElementById('select_units').options.add(optn);
	}

	// hide loading panel
	$('#loading').fadeOut();
	
	// show units panel
	elementShow('units', true, 'block');
}

function unitsGetIndexByID(intID) {
	for(var i = 0; i < vpUnits.length; i++) {
		if(vpUnits[i].id == intID) {
			return i;
		}
	}
}

function select_units_change() {
	intUnitID = document.getElementById('select_units').value;
	intUnitIndex = unitsGetIndexByID(intUnitID);
	
	// save selected unit
	intSelectedUnitID = intUnitID;
	
	// show unit info
	// var strStats = '<p>Diese Lektion enthält insgesamt ' + vpUnits[intUnitIndex].unitStats.intCountAll + ' Übungen.</p>';
	var strDesc = '<p>' + (vpUnits[intUnitIndex].description.length > 0 ? vpUnits[intUnitIndex].description : '(Keine weiteren Informationen vorhanden.)') + '</p>';
	document.getElementById('unit_props').innerHTML = '<p>' + strDesc + '</p>';
	
	// hide exercise types which aren't available
	if(vpUnits[intUnitIndex].unitStats.intCountWords == 0) { $('#liWords').fadeOut('slow'); $('#optWords').attr('checked', false); } else { $('#liWords').fadeIn('slow'); $('#optWords').attr('checked', true); }
	if(vpUnits[intUnitIndex].unitStats.intCountFIBs == 0) { $('#liFIBs').fadeOut('slow'); $('#optFIBs').attr('checked', false); } else { $('#liFIBs').fadeIn('slow'); $('#optFIBs').attr('checked', true); }
	if(vpUnits[intUnitIndex].unitStats.intCountMatchings == 0) { $('#liMatching').fadeOut('slow'); $('#optMatching').attr('checked', false); } else { $('#liMatching').fadeIn('slow'); $('#optMatching').attr('checked', true); }
	if(vpUnits[intUnitIndex].unitStats.intCountMCs == 0) { $('#liMCs').fadeOut('slow'); $('#optMCs').attr('checked', false); } else { $('#liMCs').fadeIn('slow'); $('#optMCs').attr('checked', true); }
	if(vpUnits[intUnitIndex].unitStats.intCountQuizzes == 0) { $('#liQuiz').fadeOut('slow'); $('#optQuiz').attr('checked', false); } else { $('#liQuiz').fadeIn('slow'); $('#optQuiz').attr('checked', true); }
}

// restart
function reStart() {
	if(confirm('Willst du die Übungen wirklich von Neuem starten?'))  {
		window.location.reload();
	}
}

function itmFIBsInput_updateBlocks() {
	alert('update');
}

function itmFIBsInput_keyUp(event, inputID) {
	// pressed RETURN?
	if(event.keyCode == 13) {
		// input has content?
		if($('#' + inputID).val().length == 0) {
			// ignore
		} else {
			var intBlankIndex = parseInt(inputID.replace(/fibsInput/g, ''));
		
			// final blank? => press 'next'
			if(intBlankIndex == (currentEx.blanks.length - 1)) {
				checkAndNext();
			} else {
				var strNextInput = '#fibsInput' + (intBlankIndex + 1);
				
				// move to next input
				$(strNextInput).focus();
			}
		}
	} else {
		// check for consumed blocks
		if(currentEx.bolDragDropEx) {
			// gather all given answers
			strGiven = new Array();
			
			$('#fibtext').find('input').each(function() {
				strGiven.push($(this).val());
			});
			
			// iterate through blocks and disable those that have been used already
			$('#FIBblocks span').each(function() {
				var strText = $(this).html();
				
				// text matches?
				var intIndex = strGiven.indexOf(strText);

				if(intIndex != -1) {
					$(this).addClass('disabled');
					strGiven.splice(intIndex, 1);
				} else {
					$(this).removeClass('disabled');
				}
			});
		}
	}
}

function itmWordInput_keyUp(event, inputID) {
	// pressed RETURN?
	if(event.keyCode == 13) {
		// input has content?
		if($('#' + inputID).val().length == 0) {
			// ignore
		} else {
			var intWordIndex = parseInt(inputID.replace(/itmWordInput/g, ''));

			// final word? => press 'next'
			if(intWordIndex == (currentEx.exWordTargets.length - 1)) {
				checkAndNext();
			} else {
				var strNextInput = '#itmWordInput' + (intWordIndex + 1);
				
				// move to next input
				$(strNextInput).focus();
			}
		}
	}
}

function GetUnitStats(intUnitID) {
	var strTargetPrint = '<' + intUnitID + '>';
	var intCount = new Array(0, 0, 0, 0, 0, 0);
	
	// iterate through all articles
	$(XMLDoc).find('article').each(function(){
		// sort out relevant articles associated with given unit ID
		if($(this).attr('unitidfingerprint').indexOf(strTargetPrint) != -1) {
			var intTypeID = parseInt($(this).attr('type'));
			intCount[intTypeID]++;
		}
	});
	
	// create new unit stats
	newUnitStats = new vpUnitStats(intCount[0], intCount[1], intCount[3], intCount[4], intCount[5]);
	
	// return stats
	return newUnitStats;
}
