FLN.Assessment = function(initData){
    this.n = initData.n;
    this.id = initData.id;
    this.status = initData.status;
    this.passScore = initData.passScore;	
    this.questions = initData.questions;
	this._questionsHash = {};
	for(var i = 0; i<this.questions.length; i++){
		//_questions[i].assessId = _id;
		if (YAHOO.lang.hasOwnProperty(this.questions, i)) {
			this._questionsHash[this.questions[i].id] = this.questions[i];
		}
	}
};
/**
 * gets if this assessments questions are all attempted.
 * @return {Boolean} result
 */
FLN.Assessment.prototype.allQuestionsAttempted = function(){
	//all questions are attempted if none of the scores are null
	var result = true;
	for(var i in this.questions){
		if(YAHOO.lang.isNull(this.questions[i].score)){
			var result = false;			
		}
	}
	return result;
};
/**
 * Calculates the score for this assessment and returns it. Returns null if the any of the assessment's questions are not attempted
 */
FLN.Assessment.prototype.calculateScore = function(){
	var score = null;
	if(this.allQuestionsAttempted() == true){
		score = 0;
		for (var i=0;i< this.questions.length; i++) {
			score += this.questions[i].score;
		}
	}else{
		YAHOO.log("WARNING: FLN.Assessment.prototype.calculateScore(): Trying to calculate score when not all questions are attempted.", "warn");
	}
	return score;
};
/**
 * Calculates the score for this assessment as a percentage (rounded down) and returns it. Returns null if the any of the assessment's questions are not attempted
 */
FLN.Assessment.prototype.calculatePercentageScore = function(){
	var percentageScore = null;
	if(this.allQuestionsAttempted()){
		var score = this.calculateScore();
		var numberOfQuestions = this.questions.length;
		var percentageScore = score == 0 ? 0 : Math.floor((score / numberOfQuestions)*100);
	}
	return percentageScore;
};
FLN.Assessment.prototype.passed = function(){
	var result = false;
	if(this.allQuestionsAttempted() == true){
		if(this.calculatePercentageScore() > this.passScore){
			result = true;
		}		
	}
	return result;
};
FLN.Assessment.prototype.getId = function(){
	return this.id;	
};
FLN.Assessment.prototype.getN = function(){
	return this.n;	
};
FLN.Assessment.prototype.setStatus = function(status){
	this.status = status;	
};
FLN.AssessmentController = function(){
	
	var _yl = YAHOO.lang;
	
	var _scorm = FLN.ScormAdapter;
	
	var _initData = FLN.AssessmentData;
	
	//are their assessments defined?
	var _areAssessments = _yl.hasOwnProperty(FLN.AssessmentData,"overallPassScore") ? true : false;
	
	//don't set anything up if there is no assessment data
	if (_areAssessments) {
		var _overallPassScore = _initData.overallPassScore;
		var _assessmentsArr = [];
		for (var i = 0; i < _initData.assessments.length; i++) {
			_assessmentsArr.push(new FLN.Assessment(_initData.assessments[i]));
		}
		//for convenience, hash all question objects against their Ids
		var _questionsHash = {};
		for (var i = 0; i < _assessmentsArr.length; i++) {
			_yl.augmentObject(_questionsHash, _assessmentsArr[i]._questionsHash, true);
		}
		
		//for convenience, hash all assessment objects against their Ids
		var _assessmentsHash = {};
		for (var i = 0; i < _assessmentsArr.length; i++) {
			_assessmentsHash[_assessmentsArr[i].id] = _assessmentsArr[i];
		}		
		//alert(_assessmentsArr[0].allQuestionsAttempted());
	}
    return {
        init: function(){
			if(_areAssessments && _scorm.isInitialised()){
				//if this is the first time then there is no scorm assessment data present
				//note: we map assessments to scorm's cmi.objectives.
				if(Number(_scorm.getLMSValue("cmi.objectives._count")) == 0){
					//no objectives found on LMS. create them on the LMS
					for(var i=0; i<_assessmentsArr.length; i++){
						var assess = _assessmentsArr[i];						
						var assessN = assess.getN();
						var objectiveIdParam = "cmi.objectives." + assessN + ".id";
						var objectiveStatusParam = "cmi.objectives." + assessN + ".status";						
						_scorm.setLMSValue(objectiveIdParam, assess.getId());
						_scorm.setLMSValue(objectiveStatusParam, "not attempted");						
					}
					_scorm.commitLMS();
				}else{
		        	//get any scorm data and apply it to the assessments
					for(var i=0; i<_assessmentsArr.length; i++){
						var assess = _assessmentsArr[i];						
						var assessN = assess.getN();			
						var objectiveStatusParam = "cmi.objectives." + assessN + ".status";									
						var status = _scorm.getLMSValue(objectiveStatusParam);						
						_assessmentsArr[i].setStatus(status);						
						//alert(_assessmentsArr[i].id + ": " + _assessmentsArr[i].status);
					}					
				}
			}else{
				//no assessments. do nothing.
			}
        },
        scoreAQuestion: function(qId,score){
			//normalise the questionId - perhaps it came in as a location.href
			qId = FLN.Utils.getFileName(qId);
			
			//there may be no assessments, so check there's actually questions.
			if(_areAssessments == true){
				if (_yl.hasOwnProperty(_questionsHash, qId)) {
					_questionsHash[qId].score = score;
				}else{
					YAHOO.log("WARNING: FLN.AssessmentController.scoreAQuestion(): Question with ID: " + qId + " does not exist in an Assessment.", "warn");
				}
			}else{
					YAHOO.log("FLN.AssessmentController.scoreAQuestion(): Question with ID: " + qId + " reports a score but no assessments are found in this module.", "info");				
			}
			
			//use this opportunity to check if all questions in an assessment have been answered, but only if there actually are assessments defined
			if(_areAssessments == true){
				var assess = _assessmentsHash[this.getAssessmentIdByQuestionId(qId)];
				var objectiveStatusParam = "cmi.objectives." + assess.getN() + ".status";									
				var statusVal = "";
				if(assess.allQuestionsAttempted() == true){
					//passed or failed?
					statusVal = assess.passed() ? "passed" : "failed";
				}else{
					//incomplete
					statusVal = "incomplete";
				}
				//set it on the model internally, and on the LMS
				assess.status = statusVal;
				
				//What if this assessment has previously been passed, and this time around - it is failed?
				//Behaviour is that assessments (which map to cmi.objectives) must all have a status of passed or the Module is not considered complete.
				//This would suggest a "You have already passed this assessment, your fail will not be recorded" message on the score screen,
				//and hence cmi.objectives cannot be set to "failed" if they have already been set to "passed".
				_scorm.setLMSValue(objectiveStatusParam, statusVal);
				
				//a question has been answered - so perhaps that's enough to trigger completion
				FLN.FramesetController.checkForModuleCompletion(false);				
				
				_scorm.commitLMS();
			}
        },
		getAssessmentIdByQuestionId: function(qId){
			result = null;
			for(var i = 0; i<_assessmentsArr.length; i++){
				var assess = _assessmentsArr[i];
				for(var j=0; j<assess.questions.length; j++){
					if(assess.questions[j].id == qId){
						result = assess.id
					}
				}
			}
			return result;
		},
		getAssessmentPercentageScore: function(asessId){
			return _assessmentsHash[asessId].calculatePercentageScore();
		},
		getIfAllAssessmentsPassed: function(){
			var result = true;
			for(var i = 0 ; i<_assessmentsArr.length; i++){
				if(_assessmentsArr[i].status != "passed"){
					result = false;
				}
			}
			return result;
		},
		/**
		 * returns the total percentage score for all assessments
		 */
		getAggregatePercentageScore: function(){
			var numberOfQs = 0;
			var totalScore = 0;
			for (var i = 0; i < _assessmentsArr.length; i++) {
				 for(var j=0; j<_assessmentsArr[i].questions.length;j++){
				 	numberOfQs++;
					var q = _assessmentsArr[i].questions[j];
					totalScore = totalScore + (q.score == null ? 0 : q.score);
				 }
			}
			var percentageScore = totalScore == 0 ? 0 : Math.floor((totalScore / numberOfQs)*100);
			return(percentageScore);
		}
    };
}();