/*
# $Id$
*/

/*
# @namespace DisplayLogic
*/
var DisplayLogic = {

	/*
	# @function bool execute( object stmt )
	# stmt		= An object containing all Statement model information
	#
	# Executes any DisplayLogic on the given statement to show/hide it.
	# Returns true if the statement's logic was satisifed, false otherwise.
	*/
	execute: function(stmt) {

		// Check for valid displaylogic
		if(stmt.displaylogic=='') {
			return true;
		}

		// Cycle through logic elements to determine their outcome
		var i, displayStmt = [];
		for(i=0; i<stmt.displaylogic.conditions.length; i++) {
			displayStmt.push(DisplayLogic.isSatisfied(stmt.displaylogic.conditions[i]));
		}
		displayStmt = stmt.displaylogic.bool=='or' ? displayStmt.some(function(i){return i===true;}) : displayStmt.every(function(i){return i===true;});

		// Result
		return displayStmt;
	},

	/*
	# @function bool isSatisfied()
	#
	# Determines if the given logic expression is satisfied or not.
	*/
	isSatisfied: function(expr) {

		// Get the statement referred to in the expression, and associated
		// responses given by the respondent.
		// First need to check if the statement is in the page currently being
		// viewed. If so then we can use the values in the "Response.statements"
		// and "Response.responses" Javascript objects.
		var stmt, responses;
		var position = Response.getPosition();
		if(position.sectionWeight==expr.sectionIndex && position.pageWeight==expr.pageIndex) {
			stmt = Response.statements[expr.statementIndex];
			responses = Response.responses[expr.statementIndex];
		}
		else if(expr.dependancy) {
			stmt = expr.dependancy.statement;
			responses = expr.dependancy.responses;
		}
		else {
			// THIS SHOULDN'T BE CALLED
			alert("FATAL ERROR!");
			return false;
		}

		// Recursively check that the stmt's own displaylogic is satisfied.
		// If not, then return false.
		if(!DisplayLogic.execute(stmt)) {
			return false;
		}

		// Type: radio
		// Check that the chosen AnswerOption's weight matches that defined in
		// "expr.value".
		if(stmt.AnswerType.type=='radio') {
			var optionWeight = expr.value;
			var satisfied = false;
			if(expr.logic=='equal') {
				satisfied = responses && responses[stmt.AnswerType.AnswerOption[optionWeight].id] ? true : false;
			}
			else if(expr.logic=='not-equal') {
				satisfied = responses && responses[stmt.AnswerType.AnswerOption[optionWeight].id] ? false : (responses ? true : false);
			}
			return satisfied;
		}

		// Type: checkbox
		// Check that "responses" contains an entry for each AnswerOption weight
		// defined in "expr.value".
		else if(stmt.AnswerType.type=='checkbox') {
			var satisfied = [], optionWeight;
			for(var i=0; i<expr.value.length; i++) {
				optionWeight = expr.value[i];
				satisfied.push(responses && responses[stmt.AnswerType.AnswerOption[optionWeight].id] ? true : false);
			}
			satisfied = expr.logic=="and" ? satisfied.every(function(item){ return item===true; }) : satisfied.some(function(item){ return item===true; });
			return satisfied;
		}

		// Type: text | textarea
		else if(stmt.AnswerType.type=='text' || stmt.AnswerType.type=='textarea') {
			var satisfied = false;
			var response = responses[stmt.AnswerType.AnswerOption[0].id] ? responses[stmt.AnswerType.AnswerOption[0].id] : {answer_value: ''};
			switch(expr.logic) {
				case "equal":
					satisfied = response.answer_value==expr.value;
					break;

				case "not-equal":
					satisfied = response.answer_value!=expr.value;
					break;

				case "like":
					var re = new RegExp(expr.value, 'im');
					satisfied = response.answer_value.match(re)!==null ? true : false;
					break;

				case "not-like":
					var re = new RegExp(expr.value, 'im');
					satisfied = response.answer_value.match(re)===null ? true : false;
					break;

				case "greater-than":
					var rAns = parseFloat(response.answer_value);
					var eAns = parseFloat(expr.value);
					satisfied = !isNaN(rAns) && !isNaN(eAns) && rAns>eAns;
					break;

				case "less-than":
					var rAns = parseFloat(response.answer_value);
					var eAns = parseFloat(expr.value);
					satisfied = !isNaN(rAns) && !isNaN(eAns) && rAns<eAns;
					break;

				default:
					break;
			}
			return satisfied;
		}
	}
};