var FormValidation = function () {
	return {
		forms: {},	

		init: function(formId, config) {
			this.forms['form' + formId] = config;
		},
		
		countryChanged: function(cmb) {
			var countryId = cmb.options[cmb.selectedIndex].value;
			var fieldId = cmb.name.substr(0, cmb.name.length-8);
			var stateField = cmb.form.elements[fieldId + '_state'];

			stateField.options.length = 0;
			
			if (countryId != '') {
				stateField.options[0] = new Option('Loading...');
				stateField.options[0].disabled = true;
	
				//Fetch the state list
				var ajaxConn = new this.XHConn();
				ajaxConn.connect(SolidCMS.site.root + "components/form/data/form.php", "POST", "task=countrystate&country=" + countryId, this.stateFetched, {field: stateField});
			}
		},
		stateFetched: function(xml, params) {
			try {
				var json = eval('(' + xml.responseText + ')');
				
				//Fill the combo
				params.field.options.length = 0;
				for (var i=0; i<json.data.length; i++) {
					params.field.options[i] = new Option(json.data[i]);
				}
				
			} catch(e) {
				//Error decoding states
			}
		},
		
		validateCCard: function(ccNumber) {
			var valid = "0123456789";  // Valid digits in a credit card number
			ccNumber = ccNumber.replace(/\D*/g,''); // strip non-numerics
			
			//Test number
			if (ccNumber == '4444333322221111') {
				return true;
			} else {
				var len = ccNumber.length;  // The length of the submitted cc number
				var iCCN = parseInt(ccNumber);  // integer of ccNumber
				var iTotal = 0;  // integer total set at zero
				var bNum = true;  // by default assume it is a number
				var temp;  // temp variable for parsing string
				var calc;  // used for calculation of each digit
				
				// Determine if it is the proper length 
				if(len >= 0) {
					if(len >= 15){  // 15 or 16 for Amex or V/MC
						for(var i=len;i>0;i--){  // LOOP throught the digits of the card
							calc = parseInt(iCCN) % 10;  // right most digit
							calc = parseInt(calc);  // assure it is an integer
							iTotal += calc;  // running total of the card number as we loop - Do Nothing to first digit
							i--;  // decrement the count - move to the next digit in the card
							iCCN = iCCN / 10;                               // subtracts right most digit from ccNumber
							calc = parseInt(iCCN) % 10 ;    // NEXT right most digit
							calc = calc *2;                                 // multiply the digit by two
							// Instead of some screwy method of converting 16 to a string and then parsing 1 and 6 and then adding them to make 7,
							// I use a simple switch statement to change the value of calc2 to 7 if 16 is the multiple.
							switch(calc){
							  case 10: calc = 1; break;       //5*2=10 & 1+0 = 1
							  case 12: calc = 3; break;       //6*2=12 & 1+2 = 3
							  case 14: calc = 5; break;       //7*2=14 & 1+4 = 5
							  case 16: calc = 7; break;       //8*2=16 & 1+6 = 7
							  case 18: calc = 9; break;       //9*2=18 & 1+8 = 9
							  default: calc = calc;           //4*2= 8 &   8 = 8  -same for all lower numbers
							}                                               
							iCCN = iCCN / 10;  // subtracts right most digit from ccNum
							iTotal += calc;  // running total of the card number as we loop
						}  // END OF LOOP
						
						if ((iTotal%10)==0){  // check to see if the sum Mod 10 is zero
							return true;  // This IS (or could be) a valid credit card number.
						} else {
							return false;  // This could NOT be a valid credit card number
						}
					}
				}
			}
			  
			return false;
		},
		
		validate: function(form) {
			
			//Fetch the appropriate configuration
			if (typeof(this.forms[form.name]) == 'undefined') {
				alert('Form validation configuration not found!');
			} else {
				//var regxEmail = new RegExp("^[\\w-_\.+]*[\\w-_\.]\@([\\w]+\\.)+[\\w]+[\\w]$");
				var regxEmail = new RegExp(/^((\w+\+*\-*)+\.?)+@((\w+\+*\-*)+\.?)*[\w-]+\.[a-z]{2,6}$/);
				
				var errors = [];
				for (var fieldId in this.forms[form.name]) {
					var validate = this.forms[form.name][fieldId];
					if (typeof(form[fieldId]) == 'undefined') {
						errors.push('The "' + validate.label + '" field was not found on the form!');
					} else {
						var field = form[fieldId];
						var value = field.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); //Trim

						switch (validate.type) {
						case 'text':
						case 'file':
						case 'freeform':
							
							if (value == '') {
								if (validate.required == true) {
									errors.push('"' + validate.label + '" is a required field');
								}								
							} else {
								switch (validate.validation) {
								case 'email':
									if (regxEmail.test(value) == false) {
										errors.push('Invalid email address specified for "' + validate.label + '"')
									}
									break;
								case 'ccard':
									if (this.validateCCard(value) == false) {
										errors.push('Invalid credit card number for "' + validate.label + '"')
									}
									break;
								}
							}
							
							break;
						case 'combo':
							if (validate.required) {
								if (field.options[field.selectedIndex].value == '') {
									errors.push('"' + validate.label + '" is a required field');
								}
							}
							break;
						}

					}
				}
				
				if (errors.length > 0) {
					alert('Please correct the following errors on the form before re-submitting:\n\n' + errors.join('\n'));
					return false;
				} else {
					return true;
				}
				
			}
			
			return false;
		},
		
		
		/** XHConn - Simple XMLHTTP Interface - bfults@gmail.com - 2005-04-08        **
		 ** Code licensed under Creative Commons Attribution-ShareAlike License      **
		 ** http://creativecommons.org/licenses/by-sa/2.0/                           **/
		XHConn: function()
		{
		  var xmlhttp, bComplete = false;
		  try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
		  catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
		  catch (e) { try { xmlhttp = new XMLHttpRequest(); }
		  catch (e) { xmlhttp = false; }}}
		  if (!xmlhttp) return null;
		  this.connect = function(sURL, sMethod, sVars, fnDone, objDoneParams)
		  {
		    if (!xmlhttp) return false;
		    bComplete = false;
		    sMethod = sMethod.toUpperCase();
		    try {
		      if (sMethod == "GET")
			  {
			    xmlhttp.open(sMethod, sURL+"?"+sVars, true);
			    sVars = "";
			  }
			  else
			  {
			    xmlhttp.open(sMethod, sURL, true);
			    xmlhttp.setRequestHeader("Method", "POST "+sURL+" HTTP/1.1");
			    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		      }
		      xmlhttp.onreadystatechange = function(){
		        if (xmlhttp.readyState == 4 && !bComplete)
		        {
		          bComplete = true;
		          fnDone(xmlhttp, objDoneParams);
		        }};
		      xmlhttp.send(sVars);
		    }
		    catch(z) { return false; }
		    return true;
		  };
		  return this;
		}
		
	
	};
}();


