// Global variables 
//
var textinput_overwrite = false;
var debug_flag          = false;
var is_https            = false;
var secure_url          = "";
var secure_hidden       = "";
var ref   	            = document.location.href;
var ref_path            = ref.substr(0, ref.lastIndexOf('/') + 1 ); 
var validator = {};
var submitted_once   = false;

jQuery(document).ready(function(){

	if ( jQuery("#debug_flag").attr("id") == "debug_flag" ) {
		debug_flag = true;
	}
	
	if ( jQuery("#textinput_overwrite").is("div") ) {
		textinput_overwrite = true;
	}
	
	// when user presses key, clear out defaultValue
	// remove style for defaultValue text
	//
	jQuery("form[id^='serial_'] :text, form[id^='serial_'] textarea").bind("keypress", function () {
		if ( this.defaultValue == this.value ) {
			jQuery(this).val("");
		}
		
		jQuery(this).removeClass('initial_state');
	});
	
	// when focus is given, add initial_state class for css
	// on defaultValue and put caret at the beginning.
	//
	jQuery("form[id^='serial_'] :text, form[id^='serial_'] textarea").bind("focus", function () {
		
		if (textinput_overwrite == true) {
			
			setSelectionRange(jQuery(this)[0], 0, 0);
			jQuery(this).addClass('initial_state');
		}
		else {
			if ( this.defaultValue == this.value ) {
				jQuery(this).val("");
			}
		}
	});

	// when user clicks or tabs out of field, 
	// if it's empty restore defaultValue and remove
	//	defaultValue focus style
	//
	jQuery("form[id^='serial_'] :text, form[id^='serial_'] textarea").bind("blur", function () {
		if ( this.value == "" ) {
			this.value = this.defaultValue;
		}
		jQuery(this).removeClass('initial_state');
	});
	
	//
	// Turn autocomplete = off on every input field
	//
	jQuery("form[id^='serial_'] :text").attr("autocomplete", "off");
	
	jQuery("form[id^='serial_'] input[name='address2']").val('');            // Updated 4/12/2010 for update to jquery 1.4+	
	jQuery("form[id^='serial_'] input[name='address2']").removeClass();
	jQuery("form[id^='serial_'] input[name='address2']").css("display", "none");
	jQuery("form[id^='serial_'] input[name='address2']").attr("name", "address2");
	
	//
	// for each form, activate validation on all validation fields.
	//
	jQuery("form[id^='serial_']").each(function(i) {

		is_https  = false;
		secure_url = "";
		secure_hidden = "";

		var newHtml = ""; var names   = ""; var form_id;

		var thisFormAction = jQuery(this).attr("action"); 
		
		if ( thisFormAction == "" ) {
			
			jQuery(this).attr("action", "javascript:void(0);");
		}
		//
		// handle secure form action
		//
		else if ( thisFormAction.substring(0, 5) == 'https' ) {
			
			is_https  = true;
			secure_url = thisFormAction;
			secure_hidden = "<div><input type='hidden' name='secure_url' value='" + secure_url + "'></div>";
			jQuery(this).attr("action", "javascript:void(0);");
		}
		
		if ( jQuery(this).attr("method") == "" ) {
			
			jQuery(this).attr("method", "post");
		}
		
		//
		// If the form doesn't have an id, give it one.
		//
		if ( jQuery(this).attr("id") == "" ) {

			form_id = "f_" + i;
			jQuery(this).attr("id", form_id);
		}
		else {

			form_id = jQuery(this).attr("id");
		}
		
		//
		// Get the ID part of serial_ID, store in form_id
		//
		form_id = form_id.substr( form_id.indexOf('_') + 1 );
		
		jQuery(this).attr("id", form_id);
		
		//
		// Add form id as a hidden form input
		//
		var new_hidden = "<div><input type='hidden' name='serial' value='" + form_id + "'></div>";
		
		//
		// Either the server is not reporting HTTP_REFERER variable, or an 
		// include file is causing the variable to not be used.  So we get client
		// to report this url from the dom as a hidden form input.  This discounts any php stupidity
		// we introduced by using stubs for security.  I'm ok with it.
		// works in ff2/3/ie6  but in 7, won't show alerts making js impossible to debug.
		//
		new_hidden += "<div><input type='hidden' name='referrer' value='" + ref + "'</div>";
		
		new_hidden += secure_hidden;
		
		jQuery(this).prepend(new_hidden);

		var form_label = "#" + form_id;

		//
		// For each input, get names and register valids
		//
		jQuery(this).find("input, textarea, select").each(function(j){
																					
			// collate all input names for input registry
			//
			names   += this.name + ", ";

			//
			// setup validation inputs registry- get validation parameter from the class of inputs
			//

			//
			// register checkboxes and radio buttons to grandparents (because of designers using labels)
			//
			if ( jQuery(this).is("[name$='[]']") ) {

				if ( jQuery(this).parent().parent().attr("id") == "" ) {

					group_name = jQuery(this).attr("name");

					//
					// remove the "[]", replace any spaces or non-word characters with underscores
					//
					var input_id = "group__" + group_name.substring(0, group_name.length - 2);

					input_id = input_id.replace(/[\s\W]/gi, "_");

					jQuery(this).parent().parent().attr("id", input_id);
				}
				else {

					var input_id = jQuery(this).parent().parent().attr("id");
				}
				
				//
				// The grandparent of radiobuttons and checkboxes gets the validation/modify class
				//
				var token_str = jQuery(this).parent().parent().attr("class");

			}
			else {
				//
				// If the input doesn't have an id, give it one.
				//
				if ( jQuery(this).attr("id") == "" ) {

					var input_id = form_id + "_input_" + j;  // examples: id="f0_input_3", "form1_input_3"

					jQuery(this).attr("id", input_id);
				}
				else {

					input_id = jQuery(this).attr("id");
				}

				var token_str = jQuery(this).attr("class");
			}

			input_label = "#" + input_id;

			//
			// register this #form_input as an object with properties
			// gotten from the input's class
			//
			var token_object = tokens_to_object(token_str);

			//
			//ignore any input without validation token
			//
			if ( token_object != false ) {

				validator[input_label] = token_object;
				//console.log("token object, input label" + token_object + " " + input_label);
			}

		}); // foreach input

		//
		// Add names to form_register
		//
		newHtml = "<div><input type='hidden' id='" + form_id + "_register' name='form_register' value='" + names + "'></input><div>";
		jQuery(this).append(newHtml);

		//
		// Bind submit button click event to validate_and_update_all_fields()
		//
		jQuery(this).find(":submit").click( function(){
			
			all_valid = validate_and_update_all_fields(form_label);
			
			if ( submitted_once == true ) {
				return true;
			}

			//console.log("the value of 'validate and update all fields is': " + all_valid);
			//console.log("form label is: " + form_label);
			
			if ( all_valid == true ) {
				
				//
				// send the form.
				//
				if (debug_flag == false) {
						jQuery(form_label).attr( "action", "/process_largeformat.php" );
							}
				else {
					jQuery(form_label).attr( "action", "/process_largeformat.php" );
				}
				
				submitted_once = true;
			}
			else {

				//
				// double check for autofill
				//
				all_valid = validate_and_update_all_fields(form_label);
				
				if ( all_valid == true ) {
										
					if (debug_flag == false) {
						
						if (is_https  == true) {
							
							jQuery(form_label).attr( "action", secure_url );
						}
						else {
							
							jQuery(form_label).attr("action", "/process_largeformat.php");
						}
					}
					else {
						jQuery(form_label).attr("action", "/process_largeformat.php");
					}
					
					submitted_once = true;
				}
				else {
					
					jQuery(form_label).attr("action", "javascript:void(0)");  // if it double-fails, do nothing.
				}
						
			} // else

		}); // :submit->click()

	}); //each form

	//
	// Input change Bindings
	//
	jQuery("input, textarea, select").change(function(){

		//
		// Bind onChange event to any check or radio group
		//
		if ( jQuery(this).is("[name$='[]']") ) {

			group_name = jQuery(this).attr("name");
			element_label = "group__" + group_name.substring(0, group_name.length - 2);
			element_label = "#" + element_label.replace(/[\s\W]/gi, "_");

		}
		else {

			element_label = "#" + jQuery(this).attr("id");
		}

		//
		// Bind onChange event to each validation input
		//
		if ( validator[element_label] != null ) {
			if (validator[element_label].valid != null ) {

				validate_and_update_this_field( element_label );
			}
		}
	});

}); //document ready


// Functions ---------------------------------------------------------------------
//
//

function is_valid ( type, testString ) {

	switch ( type ) {
		
		case "integer" : 

		    var regex = /^[0-9]+$/
		    break;

        case "float" :
                 
            var regex = /^[0-9]*([.]{1}[0-9]+)?$/
		    break;

		case "numberseries" :

		    var regex = /^([0-9]+[ ]*)+$/
		    break;

		case "ccsecuritycode" : 
			
			var regex = /^[0-9]{3,4}$/
			break;
	
		case "ccmonth" : case "ccday" : 
	
			var regex = /^[0-9]{2}$/
			break;

		case "ccyear" :

			var regex = /^([0-9]{2}|[0-9]{4})$/
			break;

		case "ccgenericnumber" :

			var regex = /^[0-9]{14,16}$/
			break;

		//
		// ref [http://www.regular-expressions.info/creditcard.html]
		//
		case "ccvisa" :
			
			var regex = /^4[0-9]{12}(?:[0-9]{3})?$/
			break;

		case "ccmastercard" : 
		
			var regex = /^5[1-5][0-9]{14}$/
			break;

		case "ccamericanexpress" : 
		
			var regex = /^3[47][0-9]{13}$/
			break;

		case "ccdiscover" :

			var regex = /^6(?:011|5[0-9]{2})[0-9]{12}$/
			break;

		case "ccdinersclub" :

			var regex = /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/
			break;

		case "ccjcb" :

			var regex = /^(?:2131|1800|35\d{3})\d{11}$/
			break;
		
		case "dateofbirth" :

			var regex = /^[0-9]{1,2}[\/\\ .-]?[0-9]{1,2}[\/\\ .-]?[0-9]{2,4}$/
			break;		
	
		case "email" :

			var regex =	/^\s*[a-zA-Z0-9_\-.?=]+@[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-.]{2,4})+\s*$/
			break;

		case "phone" :

			var regex = /^[0-9-+_.\(\) ]{7,27}$/
			break;

		case "name" :

			var regex = /^([a-zA-Z\-.,']+(\s)?)+$/
			break;

		case "textarea":

			var regex = /^[^\\\/<>]+$/
			break;

		case "address2" :

			return true;
			break;

		case "nonempty" :

			if (testString == '') {
				return false;
			}
			else {
				return true;
			}
			break;

		case "zipcode":

			var regex = /^[0-9\-\s]{5,10}$/
			break;

		case "visual":

			var regex = /^[a-zA-Z|\s]+$/
			break;

		case "checkedsingle" : case "checked":

			if (testString == "checked") {
				return true;
			}
			else {
				return false;
			}

		break;

		case "selected" :
			if (testString == "selected") {
				return true;
			}
			else {
				return false;
			}

		default:
			//
			// if designer puts a wrong validation type, auto-validate
			//
			return true;
	}

	var pattern = new RegExp(regex);
	var isValid = pattern.test(testString);
	var logged  = isValid.toString();

	return isValid;
}

//
// Given a string, gets the validation and the modify type
//
// modify_ID_VALIDCLASS_INVALIDCLASS,
//
// returns JSON object
// false if no tokens are present
//
// { valid : false, valdiation_type : VALIDATION_TYPE, valid_class : VALIDCLASS,
//   invalid_class : INVALIDCLASS, modifies_element: ID }
//
//
function tokens_to_object (str) {

	//debug("givem token string: " + str);

	val_regex = /validate(_[a-zA-Z][a-zA-Z0-9]+)+/gi
	mod_regex = /modify(_[a-zA-Z][a-zA-Z0-9]+)+/gi

	valid_class      = "valid";
	invalid_class    = "invalid";
	modifies_element = "default";

	vmatch  = str.match(val_regex);

	if (vmatch == null) {

		return false;
	}

	vtoken  = vmatch[0];

	validation_type = vtoken.substring( vtoken.indexOf('_') + 1 );

	mmatch  = str.match(mod_regex);

	//debug("mmatch : " + mmatch);

	if (mmatch != null) {

		mtoken  = mmatch[0];

		//
		// Lots of fun and dirty string manipulation ensues.
		//
		modStr = mtoken.substring( mtoken.indexOf('_') + 1 );

		if (modStr.indexOf('_') == -1) {
			
			modifies_element = modStr;
		}
		else {
			
			modifies_element = modStr.substring(0, modStr.indexOf('_') );
		
	  		modId_strip = modStr.substring(modStr.indexOf('_') + 1);

	  		if (modId_strip != modStr) {

				if (modId_strip.indexOf('_') != -1) {

	  				valid_class = modId_strip.substring(0, modId_strip.indexOf('_') );

					valid_strip = modId_strip.substring(modId_strip.indexOf('_') + 1);

	  				if (valid_strip != valid_class) {
	
	 	 				invalid_class = modId_strip.substring(modId_strip.indexOf('_') + 1);
	  				}
				}
				else {

					valid_class = modId_strip;
				}
			}
		}   //else
	}   // mmatch !=null

	val_obj = { "valid" : false, "validation_type" : validation_type, "valid_class" : valid_class, "invalid_class" : invalid_class, "modifies_element": modifies_element };

	//console.log(val_obj);
	return val_obj;

} // end tokens_to_object

//
// Takes input_label as '#inputId'
//
function validate_and_update_this_field ( input_label ){

		validation_type  = validator[input_label].validation_type;
		valid_class      = validator[input_label].valid_class;
		invalid_class	   = validator[input_label].invalid_class;
		modifies_element = validator[input_label].modifies_element;

		modifies_element_label = "#" + modifies_element;

		//
		// get input value, for input, select, textarea
		//

		switch (validation_type) {

			case "checked" :

				val_check = "";

				jQuery(input_label).find("input[checked]").each(function(){
					val_check = "checked";
				});

				break;

			case "checkedsingle" :

				val_check = jQuery(input_label).attr("checked");
				break;

			case "selected" :

				val_check = "";

				jQuery(input_label).children().each(function(){

					if ( jQuery(this).is("option[selected]") )  {
						
						if (jQuery(this).val() != '') {

							val_check = "selected";

						}
					}
				});

				break;
			
			case "nonempty" : 
				/*
				this = jQuery(input_label).get(0);
				
				if ( this.defaultValue == this.value ) {
					
					val_check = "";
				}*/

			default :

				val_check = jQuery(input_label).val();
				
				//
				//
				//
				var thisDom = jQuery(input_label)[0]; 
				if ( thisDom.defaultValue == val_check ) {
					
					var defaultValueFlag = true;
				}
				
				break;
		}

		if ( defaultValueFlag == true ) {
			//
			// invalidate this element if it's value is the defaultValue
			//
			var valid = false;
		}
		
		else {
			
			var valid = is_valid( validation_type, val_check );
		}

		switch ( true ) {

			case ( modifies_element == "default") :
			
				
				// Adds valid and invalid class to this element
				jQuery(input_label).removeClass(valid_class);
				jQuery(input_label).removeClass(invalid_class);
				
				jQuery(input_label).removeClass('valid');
				jQuery(input_label).removeClass('invalid');
				
				if ( valid == true ) {
					
					jQuery(input_label).addClass(valid_class);
					jQuery(input_label).addClass('valid');
					
					validator[input_label].valid = true;
				}
				else if (valid == false) {
					
					jQuery(input_label).addClass(invalid_class);
					jQuery(input_label).addClass('invalid');
					
					validator[input_label].valid = false;
				}
				
				break;

			case ( valid == true ) :

				validator[input_label].valid = true;

				//
				// remove and update class on element: modifies_element_ID
				//
				jQuery(modifies_element_label).removeClass(valid_class);
				jQuery(modifies_element_label).removeClass(invalid_class);
				jQuery(modifies_element_label).addClass(valid_class);

				break;

			case ( valid == false ) :

				validator[input_label].valid = false;

				jQuery(modifies_element_label).removeClass(valid_class);
				jQuery(modifies_element_label).removeClass(invalid_class);
				jQuery(modifies_element_label).addClass(invalid_class);

				break;

		} //switch

		//debug("validator valid?: " + validator[element_label].valid);

} //validate_and_update_this_field

//
// Returns true if all fields are valid, false otherwise
//
function validate_and_update_all_fields (form_label) {

	var all_fields_valid    = false;
	var num_of_valid_fields = 0;
	var num_valid           = 0;

	//
	// only look at inputs in the given form
	//
	jQuery(form_label).find("input, textarea, select").each(function(){

		if ( jQuery(this).is("[name$='[]']") ) {
			//
			// Look at parent's (id) instead
			//
			group_name  = "group__" + jQuery(this).attr("name");
			group_name  = group_name.substring(0, group_name.length - 2);
			group_name  = group_name.replace(/[\s\W]/gi, "_");

			element_label = "#" + group_name;
		}
		else {

			element_label = "#" + jQuery(this).attr("id");
		}

		/// BUGfix
		if ( validator[element_label] != null ) {

			if ( validator[element_label].valid ) {

				num_of_valid_fields++;
				num_valid++;
			}
			else {

				num_of_valid_fields++;
			}

			validate_and_update_this_field( element_label );
		}
	});

	if ( num_of_valid_fields == num_valid ){

		all_fields_valid = true;
	}

	toggle_error_message(all_fields_valid);

	return all_fields_valid;

} //validate_and_update_all fields


function toggle_error_message ( is_valid ) {

	var jq_selector = '#form_validation_error_msg';

	// fires every time.  problem since we are doing a double-check.
	if ( !is_valid ) {
		// @todo@
	}

	if ( !is_valid && jQuery(jq_selector).hasClass('hide') ) {
		jQuery(jq_selector).toggleClass('hide');
		
		// fires only once until corrected.
		//
		if (typeof form_validation_custom_error  == 'function') {
			form_validation_custom_error();
		}
	}
	else if ( is_valid && (jQuery(jq_selector).hasClass('hide') != true) ) {
		jQuery(jq_selector).toggleClass('hide');
	}
}

//
// Useful js debug function
//
function debug(xx) {
	
	//
	// Other browsers can't handle firebug.
	//
	if ( (typeof(console) == 'object') ) {
		if (typeof console.log == 'function' ) {
			console.log(" " + xx + " \n");
		}
	}
}

//----Included because IE sucks (L@@K at their extra code for IE 40 v FF 2 ) ---
//
// Author: Mihai Bazon, 2006
// http://www.bazon.net/mishoo/
// This code is (c) Dynarch.com, 2006.
//
// Permission is hereby granted to use this code 
// under the terms of the GNU LGPL. (www.gnu.org/licenses/lgpl.html)

var is_gecko = /gecko/i.test(navigator.userAgent);
var is_ie    = /MSIE/.test(navigator.userAgent);

function setSelectionRange(input, start, end) {
	if (is_gecko) {
		input.setSelectionRange(start, end);
	} else {
		// assumed IE
		var range = input.createTextRange();
		range.collapse(true);
		range.moveStart("character", start);
		range.moveEnd("character", end - start);
		range.select();
	}
};

function getSelectionStart(input) {
	if (is_gecko)
		return input.selectionStart;
	var range = document.selection.createRange();
	var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
	if (!isCollapsed)
		range.collapse(true);
	var b = range.getBookmark();
	return b.charCodeAt(2) - 2;
};

function getSelectionEnd(input) {
	if (is_gecko)
		return input.selectionEnd;
	var range = document.selection.createRange();
	var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
	if (!isCollapsed)
		range.collapse(false);
	var b = range.getBookmark();
	return b.charCodeAt(2) - 2;
};

