// INITIALIZE GLOBAL FORM VALIDATION VARIABLES
// VALIDATION IS THE VARIABLE WHERE ALL VALIDATION DATA WILL BE HELD
var validation = [];
// CREATE AN ARRAY OF ALL VALID DATA TYPES THAT CAN BE VALIDATED
var data_types = ["integer","float","noblanks","email","usdate","eurodate","creditcard","password","fields_match"];
// BY DEFAULT WE DON'T WANT TO BYPASS VALIDATION. IN SOME INSTANCES WE WILL, LIKE SUBMITTING WITH A DELETE BUTTON
var bypass_validation = false;

// ADD THE DISCOVER FORM FUNCTION TO THE WINDOW ONLOAD FUNCTION
if (window.addEventListener) {
	// DOM METHOD FOR BINDING AN EVENT
	window.addEventListener("load", $discoverForm, false);
} else if (window.attachEvent) {
	// IE EXCLUSIVE METHOD FOR BINDING AN EVENT
	window.attachEvent("onload",$discoverForm);
} else if (document.getElementById) {
	// SUPPORT OLDER MODERN BROWSERS
	window.onload = function() {
		$discoverForm();
	}
}

function $editValidation(method, form, field, required, type, validate, related_field) {
	if (method == "add") {
		// ADD VALIDATION - THIS OVERWRITES ANY EXISTING VALIDATION
		validation[form][field] = {id:field, required:required, type:type, validate:validate, related_field:related_field};
	} else if (method == "remove") {
		// REMOVE VALIDATION - THIS REMOVES ALL VALIDATION FOR A FIELD
		// DO NOT CLEAR THE VALIDATION FIELD. IF THEY FILL OUT AN OPTIONAL FIELD IT SHOULD STILL VALIDATE
		validation[form][field].required = false;
	}
}

function $discoverForm() {
	if ( document.getElementById && document.getElementsByTagName ) {
		
		// GET ALL FORMS ON THE PAGE
		var forms = document.getElementsByTagName('form');
		
		// LOOP THROUGH EACH FORM
		for (var i=0; i<forms.length; i++) {
			// CHECK THE FORM CLASS. IF IT DOESN'T INCLUDE THE UNIFORM CLASS DON'T PROCESS IT.
			if ( forms[i].className.toLowerCase().indexOf("uniform") == -1 ) {
				continue;
			}
			// GET THE CURRENT FORM ID. USE getAttribute HERE TO AVOID CONFLICTS WHEN A FORM
			// HAS A FIELD NAMED ID (WHICH A LOT OF A&K FORMS DO). THE CONFLICT IS THAT YOU CAN
			// ACCESS A FORM NAMED fieldName AS forms[0].fieldName. WHEN THE FIELD NAME IS ID
			// THE BROWSER ACCESSES THE INPUT OBJECT INSTEAD OF THE ATTRIBUTE ID
			//var form_id = forms[i].getAttribute('id');
			var form_id = forms[i].attributes['id'].value
			// CREATE A NEW OBJECT IN THE VALIDATION ARRAY
			// THIS WAY WE CAN SEPARATE THE FIELDS IN EACH FORM
			validation[form_id] = {};
		
			// GET ALL INPUTS IN THE CURRENT FORM
			var inputs = forms[i].getElementsByTagName('input');
			
			// LOOP THROUGH INPUTS
			for(var j=0; j < inputs.length; j++) {
				// ONLY PROCESS TEXT, PASSWORD, CHECKBOX AND RADIO INPUTS. DO NOT PROCESS BUTTON, RESET OR SUBMIT INPUTS
				if ( inputs[j].type == "text" || inputs[j].type == "password" || inputs[j].type == "checkbox" || inputs[j].type == "radio" ) {
					// DEFAULT VARIABLES
					var required = false;
					var validate = "";
					var id = inputs[j].id;
					var maxlen = 0;
					var related_field = "";
					
					// GET CLASS LIST
					var classes = inputs[j].className.split(" ");
					var pos = $arrayFindNoCase(data_types,classes);
					if (pos != -1) {
						validate = data_types[pos];
					}
					
					// CHECK TO SEE IF THE INPUT IS REQUIRED
					if ( inputs[j].className.toLowerCase().indexOf("required") != -1 ) {
						required = true;
						// FOR CHECKBOXES AND RADIO BUTTONS SET THE TYPE TO CHECKBOX OR RADIO
						if (inputs[j].type != "text") {
							validate = inputs[j].type;
						}
					}
					
					// CHECK TO SEE IF THIS IS A PASSWORD CONFIRMATION FIELD. THIS IS A SPECIAL VALIDATION SINCE WE
					// NEED TO KNOW THE ID OF THE OTHER FIELD TO COMPARE THEIR VALUES.
					for(var m=0; m < classes.length; m++) {
						if( classes[m].toLowerCase().indexOf(":") != -1 ) {
							validate = classes[m].split(":")[0];
							related_field = classes[m].split(":")[1];
						}
					}
					
					// DETERMINE MAXLENGTH, IF SPECIFIED
//					if (inputs[j].maxLength > 0) {
//						maxlen = inputs[j].maxLength;
//					}
//					var max_pos = classes.indexOf("maxlength");
//					if (max_pos > -1 and classes[max_pos + 1]) {
//						alert(max_pos);
//						alert(classes[max_pos + 1]);
//					}
					
					// UPDATE THE VALIDATION OBJECT
					$editValidation('add',form_id,id,required,inputs[j].type,validate,related_field);
				}
			}
			
			// GET ALL TEXTAREAS IN THE CURRENT FORM
			var textareas = forms[i].getElementsByTagName('textarea');
				
			// LOOP THROUGH TEXTAREAS
			for(var k=0; k < textareas.length; k++) {
				// DEFAULT VARIABLES
				var required = false;
				var validate = "";
				var id = textareas[k].id;
				
				// CHECK TO SEE IF THE INPUT IS REQUIRED
				if ( textareas[k].className.toLowerCase().indexOf("required") != -1 ) {
					required = true;
				}
				
				// UPDATE THE VALIDATION OBJECT
				$editValidation('add',form_id,id,required,textareas[k].type,validate);
			}
			
			// GET ALL SELECTS IN THE CURRENT FORM
			var selects = forms[i].getElementsByTagName('select');
				
			// LOOP THROUGH SELECTS
			for(var l=0; l < selects.length; l++) {
				// DEFAULT VARIABLES
				var required = false;
				var validate = selects[l].type;
				var id = selects[l].id;
				
				// CHECK TO SEE IF THE INPUT IS REQUIRED
				if ( selects[l].className.toLowerCase().indexOf("required") != -1 ) {
					required = true;
				}
				
				// UPDATE THE VALIDATION OBJECT
				$editValidation('add',form_id,id,required,selects[l].type,validate);
			}
			
			// ATTACH EVENT TO THE FORM ONSUBMIT
			forms[i].onsubmit = function() {
				return $validateForm(this.id);
			}
			
		} // END FOR LOOP FOR FORM
	} // END IF
} // END FUNCTION

function $validateForm(form_id) {
	// INITIALIZE ERR AND OK ARRAYS
	var err = [];
	var ok = [];
	
	// IF THE DELETE BUTTON HAS BEEN CLICKED, DON'T BOTHER VALIDATING THE FORM
	if ( bypass_validation ) {
		return true;
	} else {
		// IF A VALID FORM ID WAS PASSED IN, VALIDATE IT.
		if (validation[form_id]) {
			var obj = validation[form_id];
			for (var f in obj) {
				var valid = false;
				// VALIDATE REQUIRED FIELDS
				if (obj[f].required) {
					valid = $validateField(f,obj[f]);
					if (valid) {
						ok.push(f);
					} else {
						err.push(f);
					}
					//alert(f + " required\nIs Valid: " + valid);
				} else { // VALIDATE NON REQUIRED FIELDS WE ONLY NEED TO WORRY ABOUT TEXT FIELDS BECAUSE ALL OTHER FIELDS ARE JUST REQUIRED OR NOT
					if (obj[f].type == "text" && obj[f].validate.length > 0 && $isNotBlank($(f).value)) {
						valid = $validateField(f,obj[f]);
					} else {
						valid = true;
					} // END IF ELSE
					if (valid) {
						ok.push(f);
					} else {
						err.push(f);
					} // END IF ELSE
				} // END IF ELSE
			} // END FOR
		} // END IF
		
		// SHOW AND HIDE ERROR MESSAGES BASED ON THE OK AND ERR ARRAYS
		if(ok.length > 0) {
			for ( var j=0; j < ok.length; j++ ) {
				var n = $(ok[j]).name;
				if ($(n + "_err")) {
					$(n + "_err").className = "errorFieldHide";
				}
					
				// WALK UP THE DOM TREE UNTIL YOU FIND THE FIRST PARENT THAT IS A DIV
				var p = $(ok[j]).parentNode;
				// SINCE FCKEDITOR EMBEDS HIDDEN FIELDS AND AN IFRAME INSIDE A DIV WE MUST CHECK FOR IT FIRST
				if (p.nodeName == "DIV" && p.className == "fckEditor") {
					p = p.parentNode;
				}
				while (p.nodeName != "DIV") {
					p = p.parentNode;
				}
				/* IF THE PARENT HAS THE borderTop CLASS ASSIGNED WE NEED TO MAINTAIN IT */
				if  (p.className.toLowerCase().indexOf("bordertop") != -1) {
					p.className = "ctrlHolder borderTop";
				} else {
					p.className = "ctrlHolder";
				}
			}
		} // END IF
		
		if(err.length > 0){
			for(var i=0; i<err.length; i++){
				var n = $(err[i]).name;
				if ($(n + "_err")) {
					$(n + "_err").className = "errorField";
				}
					
				// WALK UP THE DOM TREE UNTIL YOU FIND THE FIRST PARENT THAT IS A DIV	
				var p = $(err[i]).parentNode;
				// SINCE FCKEDITOR EMBEDS HIDDEN FIELDS AND AN IFRAME INSIDE A DIV WE MUST CHECK FOR IT FIRST
				if (p.nodeName == "DIV" && p.className == "fckEditor") {
					p = p.parentNode;
				}
				while (p.nodeName != "DIV") {
					p = p.parentNode;
				}
				/* IF THE PARENT HAS THE borderTop CLASS ASSIGNED WE NEED TO MAINTAIN IT */
				if  (p.className.toLowerCase().indexOf("bordertop") != -1) {
					p.className = "ctrlHolder error borderTop";
				} else {
					p.className = "ctrlHolder error";
				}
			} // END FOR
			$(err[0]).focus();
			return false;
		} // END IF
		
		else {
			return true;
		} // END ELSE
	}
	
} // END FUNCTION

// $VALIDATEFIELD DETERMINES IF AN ELEMENT (E) IS VALID BASED ON THE VALIDATION TYPE (V) AND OPTIONALLY COMPARING IT TO A RELATED FIELD (R)
function $validateField(e,o) {
	var valid = false;
	var v = o.validate;
	var r = o.related_field;
	switch (v) {
		// VALIDATE INTEGERS
		case "integer":
			valid = $isInt($(e).value);
			break;
		// VALIDATE FLOATS
		case "float":
			valid = $isFloat($(e).value);
			break;
		// VALIDATE NO BLANKS - FIELDS THAT JUST NEED SOMETHING FILLED OUT, EXCLUDING WHITESPACE CHARACTERS
		case "noblanks":
			valid = $isNotBlank($(e).value);
			break;
		// VALIDATE EMAIL ADDRESSES
		case "email":
			valid = $isEmail($(e).value);
			break;
		// VALIDATE PASSWORDS
		case "password":
			valid = $isNotBlank($(e).value);
			//valid = $isPassword($(e).value);
			break;
		// CONFIRM THE PASSWORDS
		case "fields_match":
			if(o.required){
				valid = ( $(e).value == $(r).value && $isNotBlank($(e).value));
			} else {
				valid = ($(e).value == $(r).value);
			}
			break;
		// VALIDATE US FORMATTED DATES
		case "usdate":
			valid = $isUSDate($(e).value);
			break;
		// VALIDATE EURO FORMATTED DATES
		case "eurodate":
			valid = $isEuroDate($(e).value);
			break;
		// VALIDATE CHECKBOX FIELDS
		case "checkbox":
			var n = document.getElementsByName($(e).name);
			for (var i=0; i<n.length; i++) {
				if (n[i].checked) {
					valid = true;
					break;
				}
			}
			break;
		// VALIDATE RADIO FIELDS
		case "radio":
			var n = document.getElementsByName($(e).name);
			for (var i=0; i<n.length; i++) {
				if (n[i].checked) {
					valid = true;
					break;
				}
			}
			break;
		// VALIDATE SELECT FIELDS
		case "select-one":
			if ($(e).selectedIndex > 0) {
				valid = true;
			} else {
				valid = false;
			}
			break;
		case "select-multiple":
			if ($(e).selectedIndex > -1) {
				valid = true;
			} else {
				valid = false;
			}
			break;
		// VALIDATE CREDIT CARD NUMBERS
		case "creditcard":
			valid = $isCreditCardNumber($(e).value);
			break;
		// THE DEFAULT VALIDATION FOR A REQUIRED FIELD IS NO BLANKS
		default:
			valid = $isNotBlank($(e).value);
			break;
	}
	return valid;
}

// THIS IS A FUNCTION THAT ENSURES THAT THE CURRENT HTML IN THE FCKEDITOR IS IN THE HIDDEN INPUT FIELD THAT 
// IS SUPPOSED TO HOLD THAT DATA. FROM TESTING IT LOOKS LIKE THAT VALUE DOESN'T GET UPDATED WHEN THE SUBMIT
// BUTTON IS CLICKED. SOMEHOW IT DOES GET UDPATED BEFORE THE FORM IS SUBMITTED, BUT NOT BEFORE THE VALIDATION ROUTINE RUNS
function $validateRte(field) {
	var oEditor = FCKeditorAPI.GetInstance(field);
	document.getElementById(field).value = oEditor.GetHTML();
}

function $validateDelete(message) {
	if( confirm(message) ) {
		// UPDATE THE BYPASS VALIDATION FLAG SO THAT THE FORM VALIDATION IS NOT RUN
		// OTHERWISE THE USER HAS TO FILL OUT THE FORM IN ORDER TO DELETE THE ITEM
		bypass_validation = true;
		return true;
	} else { 
		return false;
	}
}

// THIS IS A FUNCTION THAT DUMPS THE VALIDATION OBJECT TO A DIV IF YOU WANT TO LOOK AT IT
function $showValidation() {
	if ( $('show_validation') ) {
		var div = $('show_validation');
		var content = "";
		for (var z in validation) {
			content += "<h1>" + z + "</h1>";
			//alert("form: " + z);
			for (var y in validation[z]) {
				content = content + "<p>id: " + validation[z][y].id + "<br>required: " + validation[z][y].required + "<br>type: " + validation[z][y].type + "<br>validate: " + validation[z][y].validate + "</p>";
				//alert("id: " + validation[z][y].id + "\nrequired: " + validation[z][y].required + "\ntype: " + validation[z][y].type + "\nvalidate: " + validation[z][y].validate);
			}
		}
		div.innerHTML = content;
	}
}