var errorDiv = new Array();
//var validationRules = null;
var ajaxErrors = Array();
var messages  = Array();
var validating = false;

//place config data in initevents (onload function):
/*
 validationRules = $H({field_id:{desc:'Description',func:'validationfunction'}, // run validation_validationfunction(fld)
					   field_id2:{desc:'Description2',func:['validationfunction1','validationfunction2[param]']}// run validation_validationfunction(fld) then if that succeeds, validation_validationfunction(fld,'param')
					   field_id2:{desc:'Description2',func:['validationfunction1','validationfunction2[{subparam:"subval",subparam2:"sub2val"}]']}// run validation_validationfunction(fld) then if that succeeds, validation_validationfunction(fld,'param') where param has multiple parts
					   field_id3:{desc:'Description3',func:''}, // always OK
					   submit: {button:'btnRegister'} // button will be ghosted when the form has validation errors
					  });
*/

// Event.observe($('field_id'), 'blur', function() {validateForm(this)});

/**
 * ------------------------------------------------------
 * Validate form
 * ------------------------------------------------------
 * validates form against rules defined in validationRules
 * returns true on error
 */
function validateForm(fld, ignoreTips) {
	if (!validating) {
		validating = true;

		// if there is a callback on the calling page, then call it
		if (!ignoreTips && window.preValidateFormCallback)
			if (!preValidateFormCallback(fld)) {
				validating = false;
				return(false);
			}
			
		if (typeof ignoreTips == "undefined") ignoreTips = false;

		//try{alert('validateForm ' + fld.id);} catch(e) {};
		var fldid = (fld)?fld.id:'';
		var hasErrors = false;
	
		// go through all fields in validation rules
		// first validate all except for the one that was just edited
        var vr = validationRules._object ? validationRules._object : validationRules;
		for (var i in vr) {
			if ($(i) && fldid!=i && i!='submit')
				if (!fldid) { // this test is unnecessary right now
					if (validateField(i, (fld), ignoreTips || fldid)) {
						hasErrors = true;
					} else {
						if (!fldid && !ignoreTips) { //closetip(i)
							if ($('tip_' + i))
								$('tip_' + i).innerHTML = '';
						}
					}
//				} else {
//					if ($('tip_' + i))
//						$('tip_' + i).innerHTML = '';
				}
		}
		
		//then validate the last edited field
		if (fldid)
			if (validateField(fldid, true)) hasErrors = true;
			
		// de/activate submit button
		setSubmitButton(hasErrors);
		
		// de/activate error warning header
//		if (!ignoreTips && $('tip_err_header'))
//			$('tip_err_header').style.display = hasErrors?'':'none';
		if (!hasErrors && $('tip_err_header'))
			$('tip_err_header').style.display = 'none';
		
		// if there is a callback on the calling page, then call it
		if (!ignoreTips && window.validateFormCallback)
			validateFormCallback(hasErrors,fld);
			
		validating = false;
		return(hasErrors);
	}
}

/**
 * ------------------------------------------------------
 * de/activate submit button
 * ------------------------------------------------------
 */
function setSubmitButton(hasErrors) {
	var vr = validationRules;
	if (validationRules['submit']) {
		if($(validationRules['submit']['button'])) {
			if(isset("validationRules['submit']['alt']")) {
				if(!isset("validationRules['submit']['img']")) {
					validationRules['submit']['img'] = $(validationRules['submit']['button']).src;
					//validationRules['submit']['alt'] = secure_url(validationRules['submit']['alt']);
				}
				$(validationRules['submit']['button']).src=(hasErrors?validationRules['submit']['alt']:validationRules['submit']['img']);
			} else {
				$(validationRules['submit']['button']).setOpacity(hasErrors?0.5:1);
			}
		}
	}
}

function validateFieldHandler() {
    validateForm(this);
}

/**
 * ------------------------------------------------------
 * validate a single field object
 * ------------------------------------------------------
 */
function validateThis(fld) {
	//alert('validateThis ' + fld.id);
	return(validateField(fld.id, true));
}

/**
 * ------------------------------------------------------
 * validate a single field by id
 * ------------------------------------------------------
 */
function validateField(fld, showThis, ignoreTips) {
	//alert('validateField ' + fld);
	thisHasErrors = false;
	if (typeof ignoreTips == 'undefined') ignoreTips = false;

	if (typeof validationRules['_object'] != 'undefined') validationRules = validationRules['_object'];
	
	try {
		// is there more than one validation rule?
		if (isArray(validationRules[fld].func)) {
			// loop through all rules
			for (func in validationRules[fld].func) {
				funcname = validationRules[fld].func[func];
				if (typeof(funcname) != 'string') continue;
				param = '';
				//strip out parameter if any
				if (funcname.indexOf('[')>0) {
					param = funcname.substr(funcname.indexOf('[')+1);
					param = param.substr(0,param.length-1);
					if (param.substr(0,1) != '{') 
						param = "'" + param + "'";
					param = "," + param;
					funcname = funcname.substr(0,funcname.indexOf('['));
				}
				// function might not exist because of wacky values added by prototype's Array extensions
				try {
					// execute validation_[validation function](field_id, paramIfThereIsOne);
					// validation functions return an error message when they fail
					evalScript = 'msg = validation_' + funcname + "('" + fld + "'" + param + ');';
					eval(evalScript);
					if (!ignoreTips && showThis) setError(fld,msg,showThis);
					if (msg) {
						// if the error message was not blank, we'll stop looking for errors on this field
						thisHasErrors = true;
						break;
					}
					// only show the first error on a field
				} catch(err) {}
			}
		} else if (validationRules[fld].func) {
			// this is just like above except it only does it once
			// instead of looping through an array of function names
			funcname = validationRules[fld].func;
			param = '';
			if (funcname.indexOf('[')>0) {
				param = funcname.substr(funcname.indexOf('[')+1);
				param = param.substr(0,param.length-1);
				if (param.substr(0,1) != '{') 
					param = "'" + param + "'";
				param = "," + param;
				funcname = funcname.substr(0,funcname.indexOf('['));
			}
			try {
				// execute validation_[validation function](field_id, paramIfThereIsOne);
				// validation functions return an error message when they fail
				evalScript = 'msg = validation_' + funcname + "('" + fld + "'" + param + ');';
				eval(evalScript);
				if (!ignoreTips && showThis) setError(fld,msg,showThis);
				if (msg) {
					thisHasErrors = true;
				}
			} catch(err) {}
		} else {
			setError(fld,'',showThis);
		}
	} catch(err) {}
	return(thisHasErrors);
}

/**
 * ------------------------------------------------------
 * check to see if a form can be submitted, display a message if it can not
 * ------------------------------------------------------
 */
function canSubmit() {
	if (Ajax.activeRequestCount) {
		//modal_alert('Still waiting on ajax');
		return(false);
	}
	//run validation on the entire form
	var hasErrors = validateForm(true,false);
	if ($('tip_err_header'))
		$('tip_err_header').style.display = hasErrors?'':'none';
	if (hasErrors) {
		//modal_alert('There are errors on your form.  Please correct them and try again.');
		return(false);
	} else {
		return(true);
	}
}

/**
 * ------------------------------------------------------
 * set the error condition for an input field by id
 * ------------------------------------------------------
 */
function setError(id,err,showThis,setSubmit) { //showthis is currently unused
	if (typeof err == 'undefined') err = '';
	//$(id).style.backgroundColor = (err) ? '#b64926' : '#E1FEE8';
	//save this for later - validation_ajax just returns this value
	ajaxErrors[id] = err;
	//using tooltips custom script
	var tipName = 'tip_' + id;
	
	if(err != '') delete messages[id];
	
	if ($(tipName) && !messages[id]) {
		$(tipName).innerHTML = err;
	}
	
	
	
//	if (!$(tipName))
//		Event.observe($(id), 'blur', function() { validateThis(this);});
//	setTip(id, err, showThis, false, '', '', 0, $(id).offsetHeight, 'validation_message',10);

	if ($(id).type == 'checkbox') 
		if (!$(id + '_checkborder')){
			var newdiv = document.createElement('div');
			newdiv.id = id + '_checkborder';
			newdiv.className = 'errTip_checkborder';
			newdiv.style.display = 'none';
			newdiv.onclick = function () {$(id).checked = !$(id).checked;$(id).focus()};
			
			if ($(id).offsetParent) {
				$(id).offsetParent.appendChild(newdiv);
			} else {
				$(id).appendChild(newdiv);
			}
	 	}
	
	if ($(id).type == 'checkbox') {
		if ($(id + '_checkborder'))
			$(id + '_checkborder').style.display = (err) ? '' : 'none';
	} else {
		$(id).style.borderColor = (err) ? '#b64926' : '#D8D8D8';
	}
	
	if (typeof setSubmit != "undefined") {
		if (setSubmit) {
			validateForm($(id), true);
		}
	}
}

/**
 * ------------------------------------------------------
 * set a message for an input field by id, with out causing validation error
 * ------------------------------------------------------
 */
function setMsg(id,msg) { 
	if (typeof msg == 'undefined') msg = '';
	//alert(id);
	messages[id] = msg;
	if(ajaxErrors[id] != undefined) delete ajaxErrors[id];
	var tipName = 'tip_' + id;
	if ($(tipName))
		$(tipName).innerHTML = msg;
	$(id).style.borderColor = '#D8D8D8';
}

/**
 * ------------------------------------------------------
 * initialize page
 * ------------------------------------------------------
 */
function initializeValidation() {
	if (typeof validationRules['_object'] != 'undefined') validationRules = validationRules['_object'];
	for (var fld in validationRules)
		if ($(fld)) {
			evalScript = "new Form.Element.DelayedObserver($('" + fld + "'),0.5,function() {validateForm($('" + fld + "'));});";
			eval(evalScript);
			evalScript = "Event.observe($('" + fld + "'),'change', function() {validateForm($('" + fld + "'));});";
			eval(evalScript);
			evalScript = "Event.observe($('" + fld + "'),'blur', function() {validateForm($('" + fld + "'));});";
			eval(evalScript);
			//$(fld).style.marginBottom = '20px';
			//alert($(fld).id + " " $(fld).name);
		}
}

/**
 * ------------------------------------------------------
 * get field value from field, deal with select boxes appropriately
 * ------------------------------------------------------
 */
function fldValue(fld) {
	if ($(fld).options) {
		return($(fld).options[$(fld).selectedIndex].value);
	} else {
		return($(fld).value);
	}
}

// the validation functions.
// These all begin "validation_"
// special validation functions can be added here or in the js for a specific page

//if optional parameter "nonzero" is included, zero counts as blank
function validation_required(fld,nonzero) {
	if (fldValue(fld)=='' || (nonzero!=undefined && fldValue(fld)=='0')) {
		return(validationRules[fld].desc + ' is required');
	}
}

// checkbox is checked
function validation_checked(fld) {
	if ($(fld).type == 'checkbox' && !$(fld).checked) {
		return(validationRules[fld].desc + ' must be checked');
	}
}

//Numeric
function validation_numeric(fld) {
	if (!isNumeric(fldValue(fld))) {
		return(validationRules[fld].desc + ' must be numeric');
	}
}

// Greater Than
// if val is a number, compare to that number, otherwise compare to $(val).value
function validation_gt(fld,val) {
	if(!isNumeric(val)) {
		if (fldValue(fld)*1 <= $(val).value*1)
			return(validationRules[fld].desc + ' must be greater than ' + validationRules[val].desc);
	} else {
		if (fldValue(fld)*1 <= val*1)
			return(validationRules[fld].desc + ' must be greater than ' + val);
	}
}

// Less Than
// if val is a number, compare to that number, otherwise compare to $(val).value
function validation_lt(fld,val) {
	if(!isNumeric(val)) {
		if (fldValue(fld)*1 >= $(val).value*1)
			return(validationRules[fld].desc + ' must be less than ' + validationRules[val].desc);
	} else {
		if (fldValue(fld)*1 >= val*1)
			return(validationRules[fld].desc + ' must be less than ' + val);
	}
}

// Greater Than or Equal To
// if val is a number, compare to that number, otherwise compare to $(val).value
function validation_ge(fld,val) {
	if(!isNumeric(val)) {
		if (fldValue(fld)*1 < $(val).value*1)
			return(validationRules[fld].desc + ' must be greater than or equal to ' + validationRules[val].desc);
	} else {
		if (fldValue(fld)*1 < val*1)
			return(validationRules[fld].desc + ' must be greater than or equal to ' + val);
	}
}

// Less Than or Equal To
// if val is a number, compare to that number, otherwise compare to $(val).value
function validation_le(fld,val) {
	if(!isNumeric(val)) {
		if (fldValue(fld)*1 > $(val).value*1)
			return(validationRules[fld].desc + ' must be less than or equal to ' + validationRules[val].desc);
	} else {
		if (fldValue(fld)*1 > val*1)
			return(validationRules[fld].desc + ' must be less than or equal to ' + val);
	}
}

// Equal To
// if val is a field name on the current page, compare to that, otherwise compare to val itself
function validation_eq(fld,val) {
	if($(val)) {
		if (fldValue(fld) != $(val).value)
			return(validationRules[fld].desc + ' must be equal to ' + validationRules[val].desc);
	} else {
		if (fldValue(fld) != val)
			return(validationRules[fld].desc + ' must be equal to ' + val);
	}
}

// Not Equal To
// if val is a field name on the current page, compare to that, otherwise compare to val itself
function validation_ne(fld,val) {
	if($(val)) {
		if (fldValue(fld) == $(val).value)
			return(validationRules[fld].desc + ' must not be equal to ' + validationRules[val].desc);
	} else {
		if (fldValue(fld) == val)
			return(validationRules[fld].desc + ' must not be equal to ' + val);
	}
}
// alias neq = ne
function validation_neq(fld,val) {
	return (validation_ne(fld,val));
}

//Just return the last error that was set by setError on this field
function validation_ajax(fld) {
	if (ajaxErrors[fld]!=undefined)
		if (ajaxErrors[fld])
			return(ajaxErrors[fld]);
}

//regex match 
//'match[{regex:"^[A-Za-z0-9]*$",errmsg:"must consist of nothing but letters and numbers"}]'
function validation_match(fld, params) {
	var regex = new RegExp( params.regex );
	if (!regex.test(fldValue(fld)))
		return(validationRules[fld].desc + ' ' + params.errmsg);
}

//valid email
function validation_email(fld,blank) {
	if (typeof(blank) == 'undefined')
		return(validation_match(fld,{regex:'^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[_a-z0-9-.]+(\.[a-z]{2,4})$',errmsg:'must be a valid email address.'}));
	else
		if (fldValue(fld) != '')
			return(validation_match(fld,{regex:'^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[_a-z0-9-.]+(\.[a-z]{2,4})$',errmsg:'must be blank or a valid email address.'}));

}

//exact length
function validation_length(fld,len) {
	if (fldValue(fld).length != len) {
		return(validationRules[fld].desc + ' must be ' + len + ' characters long');
	}
}

//maximum length
function validation_length_max(fld,maxlen) {
	if (fldValue(fld).length > maxlen) {
		return(validationRules[fld].desc + ' must be no more than ' + maxlen + ' characters long');
	}
}

//radio selected, this actually checks all the radio button with the same name, and checks whether atleast one is selected
function validation_radioselected(fld) {
	if($(fld).type == 'radio') {
		name = $(fld).name;
		var is_checked = false;
		all_radio_buttons = $('mainform').getInputs('radio', name);
		all_radio_buttons.each(function(radio){
			if($(radio).checked) is_checked = true;
		});
		if(!is_checked) return (validationRules[fld].desc + ' must be answered');
	}
}