/*
 * Copyright (c) 2005 Absolutely Training Limited
 * 
 * Created on 02-Dec-2005
 */
 
/* JSLint global function comment */
/*global QuestionType, TestQuestionFactory, TestPage  */ 

/**
 * Translation of the Java Test class into JavaScript
 * 
 * @author paulb
 */
function Test() {
    this.courseId = null;
    this.testName = null;
    this.courseTest = false;
    this.createdDate = new Date();
    this.score = 0;
    this.pass = false;
    this.passMark = 0;
    this.marked = false;
    this.assessment = null;
    this.questions = [];
    this.resultCategoryString = null;
}

Test.REPORT_TOTAL_LABEL = "TOTAL";


Test.prototype.getCourseId = function() {
    return this.courseId;
};

Test.prototype.getTestName = function() {
    return this.testName;
};

Test.prototype.getCreatedDate = function() {
    return this.createdDate;
};

Test.prototype.getScore = function() {
    return this.score;
};

Test.prototype.setScore = function(score) {
    this.score = score;
};


Test.prototype.isPass = function() {
    return this.pass;
};

Test.prototype.setPass = function(pass) {
    this.pass = pass;
};

Test.prototype.getPassMark = function() {
    return this.passMark;
};

Test.prototype.setPassMark = function(passMark) {
    this.passMark = passMark;
};

Test.prototype.getResultCategoryString = function() {
    return this.resultCategoryString;
};

Test.prototype.setResultCategoryString = function(str) {
    this.resultCategoryString = str;
};

Test.prototype.isMarked = function() {
    return this.marked;
};

Test.prototype.setMarked = function(marked) {
    this.marked = marked;
};

Test.prototype.getAssessment = function() {
    return this.assessment;
};

Test.prototype.setAssessment = function( assessment) {
    this.assessment = assessment;
};

Test.prototype.isCourseTest = function() {
    return this.courseTest;
};

Test.prototype.setCourseTest = function(courseTest) {
    this.courseTest = courseTest;
};

Test.prototype.generateTest = function( testContainer ) {

	this.testContainer = testContainer;
	this.courseId = testContainer.getCourseId();
	this.testName = testContainer.getName();
	this.setResultCategoryString( testContainer.getResultCategoryGroup().getResultCategoryGroupString() );
    var questionGroups = testContainer.getQuestionGroupsRecursive();
    var numberOfQuestions = testContainer.getTotalNumberOfQuestions();
    var curQuestionGroupPos;
    var curQuestionPos;
    var curQuestionGroup;
    var curQuestion;
    for (var i = 0; i < numberOfQuestions; i++) {
        curQuestionGroupPos = Math.floor( Math.random() * questionGroups.length );
        curQuestionGroup = questionGroups[curQuestionGroupPos];

	if ( curQuestionGroup == null ) {
		alert ("Error: incorrect number of questions in questiongroup");
	}

        questionGroups.splice(curQuestionGroupPos, 1);  // remove the selected element
        curQuestionPos = Math.floor( Math.random() * curQuestionGroup.getQuestions().length );
        curQuestion = curQuestionGroup.getQuestions()[curQuestionPos];
        if (curQuestion.getType() == QuestionType.ROMAN_NUMERAL ) {
            this.addQuestion(TestQuestionFactory.createRomanNumeral(curQuestion));
        } else if (curQuestion.getType() == QuestionType.TRUE_FALSE ) {
            this.addQuestion(TestQuestionFactory.createTrueFalse(curQuestion));
        } else if (curQuestion.getType() == QuestionType.RANDOM ) {
            this.addQuestion(TestQuestionFactory.createRandomQuestion(curQuestion));
        } else {
            this.addQuestion(TestQuestionFactory.createMultipleChoice(curQuestion));
        }
    }
    
};

Test.prototype.getQuestions = function() {
    return this.questions;
};

Test.prototype.addQuestion = function(question) {
	question.setOrderNum( this.questions.length + 1);
    this.questions.push(question);
};

Test.prototype.getQuestion = function(index) {
    return this.questions[index];
};

Test.prototype.getTestPages = function( numberPerPage ) {
    var testPages = [];
    var questions = this.getQuestions();
	// ensure there is at least one page
    var lastIndex = Math.min( numberPerPage - 1, questions.length - 1 );
   	testPages.push( this._makeTestPage( questions, 0, lastIndex ) );
   	
    for (var firstIndex = numberPerPage; firstIndex < questions.length; firstIndex+= numberPerPage ) {
    	lastIndex = Math.min( firstIndex + numberPerPage - 1, questions.length - 1 );
    	testPages.push( this._makeTestPage( questions, firstIndex, lastIndex ) );
	}    
    
    return testPages;
};

Test.prototype._makeTestPage = function( questions, firstIndex, lastIndex ) {
	var result = new TestPage( firstIndex + 1, lastIndex + 1, questions.length );
    for (var i = firstIndex; i <= lastIndex; i++) {
    	result.addQuestion( questions[i] );
	}
	
	return result;
};


/**
 * Updates tests {@link AnswerChoice} objects based on the content of a learner response array.
 * Learner responses are in the following format: 2 for second answer choice selected, 1,4 for
 * first and fourth answer choice are selected. Updates total figure in Test Question Summary
 * objects.
 * 
 * @throws RuntimeException, if the passed in list of responses is longer than the amount of
 * questions available to this test.
 */
 /*
Test.prototype.updateSummaryObject = function(responses) {

    for (int i = 0; i < responses.length; i++) {
        TestQuestion curQuestion = (TestQuestion) getQuestions()[i];
        List<AnswerChoice> answerChoices = curQuestion.getAnswerChoices();
        TestQuestionSummary tqs = Application.getInstance().getTestSummaryManager()
                .getOrCreateTestQuestion(booking.getCourse(), booking.getUser().getCompany(),
                        booking.getTrainingPeriod(), curQuestion.questionId,
                        curQuestion.getQuestionTextWithoutNumber());
        boolean correctlyAnswered = true;
        String choices = "";

        if (curQuestion instanceof RomanNumeralQuestion) {
            for (int o = 0; o < answerChoices.length; o++) {
                AnswerChoice ac = answerChoices[o];
                if (ac.isSelected()) {
                    choices = ac.getAnswerText();
                    break;
                };
            };
            int count = 1;
            for (TestAnswer a : curQuestion.getPossibleAnswers()) {
                TestAnswerSummary ans = Application.getInstance().getTestSummaryManager()
                        .getOrCreateTestAnswer(tqs, a.getAnswer().getAnswerText());
                boolean selected = (choices.length() > 0) ? TestUtils.getNumericChoices(choices).contains(String.valueOf(count)) : false;
                if (selected == a.getAnswer().isCorrect()) {
                    ans.setCorrect(ans.getCorrect() + 1);
                };
                count++;
            };
        } else {
            // logic needs to loop through all answer choices, because true false questions could
            // have multiple correct answerchoice                
            for (int o = 0; o < answerChoices.length; o++) {
                AnswerChoice ac = answerChoices[o];

                TestAnswerSummary ans = Application.getInstance().getTestSummaryManager()
                        .getOrCreateTestAnswer(tqs, ac.getAnswerText());
                if (ac.isSelected() == ac.isCorrect()) {
                    ans.setCorrect(ans.getCorrect() + 1);
                };
            };
        };

        if (curQuestion.isCorrectlyAnswered()) {
            tqs.setCorrect(tqs.getCorrect() + 1);
        };
    };
};
*/

/**
 * Updates tests {@link AnswerChoice} objects based on the content of a learner response array.
 * Learner responses are in the following format: 2 for second answer choice selected, 1,4 for
 * first and fourth answer choice are selected. Updates total figure in Test Question Summary
 * objects.
 * 
 * @throws RuntimeException, if the passed in list of responses is longer than the amount of
 * questions available to this test.
 */
 /*
Test.prototype.updateFromLearnerResponse = function( responses) {
    if (responses.length > getQuestions().length) {
        throw new RuntimeException("Test has received too many responses: " + responses.length
                + ". It only contains " + getQuestions().length + " questions.");
    };
    for (int i = 0; i < responses.length; i++) {
        TestQuestion curQuestion = (TestQuestion) getQuestions()[i];
        List<String> learnerResponse = Arrays.asList(responses[i].split(","));
        List<AnswerChoice> answerChoices = curQuestion.getAnswerChoices();
        boolean correctlyAnswered = true;
        for (int o = 0; o < answerChoices.length; o++) {
            AnswerChoice ac = answerChoices[o];
            ac.setSelected(learnerResponse.contains(String.valueOf(o + 1)));
            correctlyAnswered = correctlyAnswered && (ac.isSelected() == ac.isCorrect());
        };
        curQuestion.setCorrectlyAnswered(correctlyAnswered);
    };

    invalidateSerializedTest();
};
*/

Test.prototype.markTest = function() {
    var wrongQuestions = 0;
    for (var i = 0; i < this.questions.length; i++) {
        var curQuestion = this.questions[i];
        var choices = curQuestion.getAnswerChoices();
        for ( var j = 0; j < choices.length; j++ ) {
        	var answerChoice = choices[i];
            if (answerChoice.isSelected() && !answerChoice.isCorrect()) {
                wrongQuestions++;
                break;
            }
            if (answerChoice.isCorrect() && !answerChoice.isSelected()) {
                wrongQuestions++;
                break;
            }
        }
    }
    
    var score = (this.questions.length - wrongQuestions) * 100 / this.questions.length;
    this.setScore(score);
    var catGroup = this.testContainer.getResultCategoryGroup();
    var assessment = catGroup.getCategoryForScore(this.getScore()).getRatingLabel();
    this.setAssessment(assessment);
    this.setPassMark(catGroup.getPassMark());
    if (catGroup.isPassMark(this.getScore())) {
        this.setPass(true);
    }
    this.setMarked(true);
};

