/*
 *  Calculates Points, Hours, Semester GPA and Overall GPA 
 *  
 *  @package GPA_Calculator
 *  @category Registrar
 *  @author Paul Gilzow, Web Communications, University of Missouri
 *  @copyright 2008
 *  @uses prototype.js
 *  @uses scriptaculous.js  
 */

/**
 *  The total number of classes that will be evaluated
 */
var $classes 			= 8;
/**
 * id of the element that will display our error messages
 */
var $errContainerID 	= 'errmsgs-container';
/**
 * id of the element that will display our calculated results
 */
var $resultsContainerID = 'results-container';	


var $aryGPAErrors		= new Array();
var $boolError 			= false;
var $fltTotalPoints		= 0;
var $fltTotalHours		= 0;
var $fltSemesterGPA		= 0;
var $fltOveralGPA		= 0;


/**
 *  The main function.  Triggers the error checking, performs the calculations, and displays results
 *  @return boolean false
 */
function calcTotals(){
	/* First we need to reset our values from any previous calculations */
	$boolError 		= false;
	$fltTotalHours 	= 0;
	$fltTotalPoints = 0;
	$fltSemesterGPA = 0;
	$fltOveralGPA	= 0;
	$aryGPAErrors		= new Array();
	
	_showErrContainer(false);
	
	checkForErrors();
	
	if($boolError){
		_displayErrMsg();	
	} else {
		var $fltPreviousPoints 	= $('prevGPA').value * $('prevHours').value;
		
		$fltSemesterGPA = $fltTotalPoints/$fltTotalHours;
		$fltOveralGPA = (($fltTotalPoints + $fltPreviousPoints)/($fltTotalHours + Number($('prevHours').value)));
		$fltOveralGPA = $fltOveralGPA.toFixed(4);
		
		$('pointTotal').update($fltTotalPoints.toFixed(2));
		$('hourTotal').update($fltTotalHours);
		$('semesterGPA').update($fltSemesterGPA.toFixed(4));
		$('overallGPA').update($fltOveralGPA);
		new Effect.Highlight($resultsContainerID,{duration:2,startcolor:'#FFCD55',queue:'end'});
	}
	
	return false;
}

/**
 * Checks all applicable inputs and looks for possible errors.  If any are encountered, adds an error message to the aryGPAErrors array
 */
function checkForErrors(){
	var $prevGPA 	= $('prevGPA');
	var $prevHours 	= $('prevHours');
	
	if($prevGPA.value != ''){
		if(isNaN($prevGPA.value)){
			$msg = 'The value you have entered for Previous GPA does not appear to be valid.  Please enter a valid number.';
			_addErrorMsg($msg);
		} else if($prevGPA.value > 4){
			$msg = 'Your Previous GPA can not be greater than 4.0.';
			_addErrorMsg($msg);
		}	
	} else {
		$prevGPA.value = 0;
	}
	
	if($prevHours.value != ''){
		if(isNaN($prevHours.value)){
			$msg = 'The value you have entered for Previous Hours does not appear to be valid. Please enter a valid number.';
			_addErrorMsg($msg);
		}
	} else {
		$prevHours.value = 0;
	}
	
	var $i = 1;
	while($i <= $classes){
		$grade 	= $('grade_' + $i);
		$hour 	= $('hours_' + $i);
		if($grade.value == '' && $hour.value != '') {
			$msg = 'You have not selected a grade value for Class ' + $i + '.  In order to calculate the GPA, ' +
			'I\'ll need you to select a grade value.';
			_addErrorMsg($msg);
		} else if($grade.value != '' && $hour.value == '') {
			$msg = 'You have not entered the number of hours for Class ' + $i + '. In order to calculate the GPA, I\'ll need ' +
			'you to enter in the number of hours.';
			_addErrorMsg($msg);
		} else if(isNaN($hour.value)) {
			$msg = 'The number of Hours you have entered for Class ' + $i + ' does not appear to be valid.  Please enter in a ' +
			'valid number.';
			_addErrorMsg($msg);
		} else if (isNaN($grade.value)) { //shouldnt ever happen, but just in case
			$msg = 'The Grade you have selected for Class ' + $i + ' does not appear to be valid.  Please select a Grade '
				+ ' from the list.';
				_addErrorMsg($msg);		
		} else if($grade.value != '' && $hour.value !='') {
			//at this point, we should have a valid selection for grade, and a valid integer for hours.
			$fltTotalHours = $fltTotalHours + Number($hour.value);
			$fltTotalPoints = $fltTotalPoints + ($grade.value*$hour.value);
		}			
		
		++$i;
	}				
}

/**
 * Adds an error message to the aryGPAErrors array
 * @param {String} $strMsg
 * @return void
 */
function _addErrorMsg($strMsg){
	if(!$boolError){
		$boolError = true;
	}
	$aryGPAErrors.push($strMsg);	
}

/**
 * Takes each error message in the aryGPAErrors array and places it into a list item inside the error container
 * 
 * @return void
 */
function _displayErrMsg(){
	var errContainer	= $($errContainerID);
	var errIntro 		= new Element('p',{id:'errors-intro'}).update('The following errors were encountered:');
	var errList 		= new Element('ul',{id:'errors-list'});
	var i				= 1;
	
	errContainer.update('');//empty the container from any previous errors
	
	errContainer.appendChild(errIntro);
	errContainer.appendChild(errList);
	
	$aryGPAErrors.each(function(strError){
			var errID = 'error-' + i;
			var errItem = new Element('li',{id:errID}).update(strError);
			errList.appendChild(errItem);
			++i;
		}
	);
	
	_showErrContainer(true);
}

/**
 * Triggers the BlindUp or BlindDown effects on the error container
 * 
 * @param {Boolean} $boolShow
 * @return void
 */
function _showErrContainer($boolShow){
	if($boolShow){
		new Effect.BlindDown($errContainerID,{queue:'end'});
    } else {
    	new Effect.BlindUp($errContainerID,{queue:'front'}); 
	}	
}