/********************************************************************
* @name iFoldRNA Errors
* @abstract - Allows users to create an account 
* @since Feb 21, 2006
* -------------------------------------------------------------------/
*
* 				Jameson Lopp jameson@unc.edu
* @author		Adi Unnithan adi@unc.edu
*				Daniel Watson dcwatson@email.unc.edu
*********************************************************************/

/*
This file needs some documentation:

iFoldRNAErrors provides a nice javascript wrapper for error-handling. It can
be used to catch errors before hitting the server-side. Here is an example
of a function that uses iFoldRNAErrors:

-------------------------------------------------------------------------
var validateRegister = function() {
	
	var errors = new iFoldRNAErrors('ALERT');
	errors.setErrorAction("ERRORID.style.border='1px solid #9F2727'");
	var fieldsArr = ['username', 'password', 'confirm_pass', 'namefirst', 'namelast', 'email', 
					 'organization'];

	errors.reset(fieldsArr, "fieldNode.style.border='1px solid #C3DADF'");
	
	errors.checkNotNull(fieldsArr);
	errors.checkMinSize('username', 3);
	errors.checkValidPassword('password');
	errors.checkFieldsMatch('password', 'confirm_pass');
	errors.checkIsEmail('email');
	
	if (errors.hasErrors()) {
		errors.show();
		return false;
	}
	return true;
}
-------------------------------------------------------------------------

1. 	The constructor "new iFoldRNAErrors()" accepts either 'ALERT' or a div box
	to display the errors in.

2.	setErrorAction() takes javascript as a parameter -- this JS is called
	on the specific element that has an error (use ERRORID).

3.	reset() takes an array of the field IDs as well as javascript that shows
	what the normal state of those fields are -- this is the opposite of
	setErrorAction().

4.	show() simply displays all of the errors into whatever div box or alert
	was specified in the constructor.

*/

function iFoldRNAError(id, msg) {
	
	this._fieldId = id;
	this._errMsg = msg;
	
	iFoldRNAError.prototype.getId = function() {
		return this._fieldId;
	}
	
	iFoldRNAError.prototype.getMsg = function() {
		return this._errMsg;
	}
}


function iFoldRNAErrors(out) {
	
	this._errors = new Array;
	if (out != 'ALERT')
		this._outId = $(out);
	else
		this._outId = out;
	this._outId.innerHTML = "";
	this._normAct = "";
	this._errAct = "";
	this._internalnullexcept = "";
	
	iFoldRNAErrors.prototype.reset = function(fieldArray, normalAction) {
		// set elements to default state
		for (var i=0;i<fieldArray.length;i++) {
			var fieldNode = $(fieldArray[i]);
			eval(normalAction);
		}
		
		// hide errors dialog
		this.hide();
	}
	
	iFoldRNAErrors.prototype.setErrorAction = function(jsAction) {
		this._errAct = jsAction;
	}
	
	iFoldRNAErrors.prototype.checkNotNull = function(fieldsArr, exceptions) {

		// build exceptions
		var exceptionJS = 'true';
		if (exceptions || this._internalnullexcept != "") {
			var exceptionsArray = Array();
			if (exceptions) exceptionsArray = exceptions.split(",");
			var internalExceptionsArray = this._internalnullexcept.split(",");
			exceptionsArray = exceptionsArray.concat(internalExceptionsArray);
			if (exceptionsArray[0] != null) { exceptionJS = "fieldsArr[i] != '" + exceptionsArray[0] + "'"; }
			for (var i=1;i<exceptionsArray.length;i++) {
				if (exceptionsArray[i] != "") {
					exceptionJS += "&& fieldsArr[i] != '" + exceptionsArray[i] + "'";
				}
			}
		}
		// first let's check everything is not null
		for (var i=0;i<fieldsArr.length;i++) {
			if (($(fieldsArr[i]).value == "") && eval(exceptionJS)) {
				this.add(fieldsArr[i], fieldsArr[i] + ' was not filled out');
			}
		}
	}
	
	iFoldRNAErrors.prototype.checkDependency = function(node, type, relatedTo) {
		if (type == 'xor') {
			if ($(node).value != "") {
				if ($(relatedTo).value != "") {
					this.add(relatedTo, "either " + relatedTo + ' or ' + node + ' should be filled out, but not both');
				}
				this._internalnullexcept += relatedTo + ",";
			}
		} else if (type == 'and') {
			if ($(node).value != "") {
				if ($(relatedTo).value == "") {
					this.add(relatedTo, relatedTo + ' should be filled out, since ' + node + ' was filled out');
				}
			}
		}
	}
	
	iFoldRNAErrors.prototype.checkMinSize = function(fieldId, size) {
		var fieldVal = $F(fieldId);
		if (fieldVal.length < size) {
			var err = new iFoldRNAError(fieldId, fieldId + ' needs to be greater than or ' + size + ' characters.');
			this._errors.push(err);
		}
	}
	
	iFoldRNAErrors.prototype.checkMaxSize = function(fieldId, size) {
		var fieldVal = $F(fieldId);
		if (fieldVal.length > size) {
			var err = new iFoldRNAError(fieldId, fieldId + ' needs to be lesser than ' + size + ' characters.');
			this._errors.push(err);
		}
	}
	
	iFoldRNAErrors.prototype.checkMinValue = function(fieldId, sizeOrNode) {
		var fieldVal = $F(fieldId);
		var value = (isNaN(parseFloat(sizeOrNode))) ? $F(sizeOrNode) : sizeOrNode;
		if (parseFloat(fieldVal) < parseFloat(value)) {
			var err = new iFoldRNAError(fieldId, fieldId + ' needs to be greater than or equal to ' + sizeOrNode);
			this._errors.push(err);
		}
	}
	
	iFoldRNAErrors.prototype.checkMaxValue = function(fieldId, sizeOrNode) {
		var fieldVal = $F(fieldId);
		var value = (isNaN(parseFloat(sizeOrNode))) ? $F(sizeOrNode) : sizeOrNode;
		if (parseFloat(fieldVal) > parseFloat(value)) {
			var err = new iFoldRNAError(fieldId, fieldId + ' needs to be less than or equal to ' + sizeOrNode);
			this._errors.push(err);
		}
	}
	
	iFoldRNAErrors.prototype.checkValidPassword = function(pass) {
		var passVal = $F(pass);
		if (passVal.length < 6) {
			var err = new iFoldRNAError(pass, 'Password should be greater than or equal to 6 characters in length.');
			this._errors.push(err);
		}
	}
	
	iFoldRNAErrors.prototype.checkFieldsNotMatch = function(args) {
		var matchAgainst = $F(arguments[0]);
		for (var i=1;i<arguments.length;i++) {
			if ($F(arguments[i]) == matchAgainst) {
				var err = new iFoldRNAError(arguments[i], arguments[i] + ' should not match ' + arguments[0] + '.');
				this._errors.push(err);
			}
		}
	}
	
	iFoldRNAErrors.prototype.checkFieldsMatch = function(args) {
		var matchAgainst = $F(arguments[0]);
		for (var i=1;i<arguments.length;i++) {
			if ($F(arguments[i]) != matchAgainst) {
				var err = new iFoldRNAError(arguments[i], arguments[i] + ' does not match ' + arguments[0] + '.');
				this._errors.push(err);
			}
		}
	}
	
	iFoldRNAErrors.prototype.checkIsEmail = function(email) {
		if (! ($F(email).search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1)) {
			var err = new iFoldRNAError(email, 'Not a valid email address!');
			this._errors.push(err);
		}
	}

 iFoldRNAErrors.prototype.checkIsRNA = function(email) {
		if (! ($F(email).search(/^[ACGU]$/) != -1)) {
			var err = new iFoldRNAError(email, 'Not a valid RNA sequence');
			this._errors.push(err);
		}
	}

	iFoldRNAErrors.prototype.checkIsNumber = function(number) {
		var objRegExp = /(^-?\d\d*$)/;

		if (! ($F(number).search(/(^-?\d\d*$)/) != -1)) {
			var err = new iFoldRNAError(number, 'Not a valid integer');
			this._errors.push(err);
		}
	}
		
	iFoldRNAErrors.prototype.add = function(fieldId, errMsg) {
		var error = new iFoldRNAError(fieldId, errMsg);
		this._errors.push(error);
	}
	
	iFoldRNAErrors.prototype.hide = function() {
		if (this._outId != 'ALERT') Element.hide(this._outId);
	}
	
	iFoldRNAErrors.prototype.show = function() {
		var allErrors = "";
		if (this._outId != 'ALERT') Element.show(this._outId);
		var errHandler = this._errAct.replace(/ERRORID/g, "$(this._errors[i].getId())");
		var errHandler = errHandler.replace(/ERRORMSG/g, "$(this._errors[i].getMsg())");
		for (var i=0;i<this._errors.length;i++) {
			eval(errHandler);
			allErrors += this._errors[i].getMsg();
			if (this._outId != 'ALERT') allErrors += "<br/>";
			allErrors += "\n";
		}
		if (this._outId != 'ALERT') this._outId.innerHTML = allErrors;
		else alert(allErrors);
	}
	
	iFoldRNAErrors.prototype.hasErrors = function() {
		return (this._errors.length > 0);
	}
}
