// forms.js - functions for validating and formating forms in HTML pages

// Main function called during the form 'onSubmit()' event
function validateForm(formId, exceptionList) {
	// Object test for js support sufficient for running this script.
	// Fallback is server validation (which is more stringent anyway)
	if(!document.getElementById || !document.getElementById(formId)) {
		return true;
	}
	
	// Clean up any previous error highlighting
	removeFormElementCssErrorClass();

	// Begin validation work
	var validity = false;
	var frm = document.getElementById(formId);

	// Map form ids to the proper form field validator constructor
	var fvConstructors = new Array();
	fvConstructors['signupForm'] = _signupFormFieldValidator;
	fvConstructors['loginForm'] = _loginFormFieldValidator;
	fvConstructors['contactForm'] = _contactFormFieldValidator;

	// Make sure we have a validator for this form first
	if(!fvConstructors[frm.id]) {
		return true;
	}

	// instantiate the appropriate fieldValidator for this form
	var FV = new fvConstructors[frm.id]();

	var container = document.getElementById('content');
	var lbls = frm.getElementsByTagName('label');
	var fields = frm.getElementsByTagName('input');

	var lblNames = new Array();
	for(var i=0; i<lbls.length; i++) {
		var k = lbls[i].getAttributeNode('for').value;
		var v = '';
		if(lbls[i].childNodes[0].nodeValue) {
			v = lbls[i].childNodes[0].nodeValue;
		} else {
			v = '';
		}
		lblNames[k] = v;
	}

	var validationErrors = new Array();
	var validationErrorList = '';
	var validationErrorCount = 0;

	for(var i=0; i<fields.length; i++) {
		var field = fields[i];

		if(field && field.id && field.name) {
			// set the field in the FV instance
			FV._setField(field.id);
			
			// validate the field's value
			if(FV._validateField() == false) {
				if(field.type != 'radio') {
					var ek = field.id;
				} else {
					var ek = field.name;
				}
				
				validationErrorList += "<p>" + lblNames[ek] + " (" +  FV._getFieldError() + ")</p>\n";
				validationErrorCount ++;
				
				field.className = field.className.replace(/\s*error/gi, '') + ' error';
			} else {
				field.className = field.className.replace(/\s*error/gi, '');
			}
		}
	}

	if(validationErrorCount>0) {
	
		if(document.getElementById("error-box")) {
			container.removeChild(document.getElementById("error-box"));
		}

		if(document.getElementById("alert-box")) {
			container.removeChild(document.getElementById("alert-box"));
		}
		
		if(document.getElementById("success-box")) {
			container.removeChild(document.getElementById("success-box"));
		}

		if(document.getElementById("message")) {
			container.removeChild(document.getElementById("message"));
		}

		var errBox = document.createElement('div');
		errBox.id = "message";
		errBox.className = "errors";
		errBox.innerHTML = "<h3>Some Fields Failed Validation:</h3>\n" + validationErrorList + "\n<a class=\"close\" href=\"#\" onclick=\"return hideDomNode('message');\" title=\"Close this message\">&times;</a>\n";
		container.insertBefore(errBox, container.getElementById('content'));
	} else {
		// remove the error box if it exists since js validation is passed at this 
		// point, and going 'back' should not display any old js errors
		if(document.getElementById("message")) {
			container.removeChild(document.getElementById("message"));
		}
		validity = true;

	}
	
	if(validity == false) {
		window.scrollTo(0,0);
	}

	return validity;
}

//  'Class' for validating fields in the signup form
function _signupFormFieldValidator() {

	this._validateField = function() {
		if(this._field.id.toLowerCase() == 'fname' || this._field.id.toLowerCase() == 'lname') {
			this._errorMessage = 'Required - letters only with hyphen(-) and apostrophe(\') as necessary';
			return this._validateNamePart(this._value);
		}

		if(this._field.type=='radio' && this._value==false) {
			this._errorMessage = 'You must select an option';
			return false;
		}

		if(this._field.id.toLowerCase() == 'email') {
			this._errorMessage = 'Invalid email address';
			return this._validateEmail(this._value);
		}
		
		if(this._field.id.toLowerCase() == 'email_check') {
			var email = document.getElementById('email');
			this._errorMessage = 'Email addresses do not match';
			return this._validateEmailMatch(this._value, email.value);
		}

		if(this._field.id.toLowerCase() == 'password') {
			this._errorMessage = 'Invalid password, must be atleast 6 characters long';
			return (this._field.value.length>6); // Check this against server side length
		}

		if(this._field.id.toLowerCase() == 'password_check') {
			var password = document.getElementById('password').value;
			this._errorMessage = 'Passwords do not match';
			return this._field.value == password ? true : false;
		}

		if(this._field.id.toLowerCase() == 'terms_accepted' || this._field.id.toLowerCase() == 'tos') {
			this._errorMessage = 'You must accept the conditions before proceeding';
			return this._validateCheckbox(this._field.checked);
		}

		if(this._field.type == 'select-one' && this._field.options.selectedIndex==0) {
			this._errorMessage = 'You must choose an option';
			return false;
		}

		return true; // Catch-all for fields not specified above
	}
}

_signupFormFieldValidator.prototype = new dataValidator();
_signupFormFieldValidator.prototype.constructor = _signupFormFieldValidator;



function _loginFormFieldValidator() {
	this._validateField = function() {

		if(this._field.id.toLowerCase() == 'email') {
			this._errorMessage = 'Invalid email address';
			return this._validateEmail(this._value);
		}
		
		if(this._field.id.toLowerCase() == 'password') {
			this._errorMessage = 'Invalid password';
			return this._validateNotEmpty(this._field.value);
		}

		return true; // Catch-all for fields not specified above
	}
}

_loginFormFieldValidator.prototype = new dataValidator();
_loginFormFieldValidator.prototype.constructor = _contactFormFieldValidator;



function _contactFormFieldValidator() {

	this._validateField = function() {
		if(this._field.id.toLowerCase() == 'name') {
			this._errorMessage = 'Please include your full name';
			return this._validateFullName(this._value);
		}
		
		if(this._field.id.toLowerCase() == 'phone') {
			this._errorMessage = 'Please include your phone number';
			return this._validatePhone(this._value);
		}
		
		if(this._field.id.toLowerCase() == 'email') {
			this._errorMessage = 'Invalid email address';
			return this._validateEmail(this._value);
		}
		
		if(this._field.id.toLowerCase() == 'company') {
			this._errorMessage = 'Please include your company\'s name';
			if(this._value == '' || this._value == false) {
				return false;
			} else {
				return true;
			}
		}
		
		if(this._field.id.toLowerCase() == 'textArea') {
			this._errorMessage = 'Please provide a description of your request';
			if(this._value == '' || this._value == false) {
				return false;
			} else {
				return true;
			}
		}

		return true; // Catch-all for fields not specified above		
	}
}

_contactFormFieldValidator.prototype = new dataValidator();
_contactFormFieldValidator.prototype.constructor = _contactFormFieldValidator;



// Data validator 'class'
function dataValidator() {
	
	this._setField = function(fieldId) {
		this._field = document.getElementById(fieldId);

		if(this._field.type=='text' || this._field.type=='textarea' || this._field.type=='checkbox') {
			this._value = this._field.value.toString();
		} else if(this._field.type=='radio') {
			var radioOptions = document.getElementsByName(this._field.name);
			var radioSelected = false;
			var radioValue = false
			for(var i=0; i<radioOptions.length; i++) {
				if(radioOptions[i].checked == true) {
					radioSelected = true;
					radioValue = radioOptions[i].value;
				}
			}
			this._value = radioValue;
		} else if(this._field.type=='select-one') {
			this._value = this._field.options[this._field.selectedIndex].value;
		} else {
			this._value = false;
		}
	}

	this._unSetField = function(fieldId) {
		this._fieldId = false;
		this._field = false;
	}

	this._getFieldError = function() {
		if(this._errorMessage) {
			return this._errorMessage;
		} else {
			return false;
		}
	}

	this._validateInteger = function(int) {
		var validity = false;
		if(parseInt(int)==int-0) {
		    validity = true;
		}
		return validity;
	}

	this._validateNotEmpty = function(str) {
		var validity = false;
		if (str.length && str.length > 0) {
		    validity = true;
		}
		return validity;
	}

	this._validateEmail = function(emailAddress) { // Checks if a given email address is valid
		var validity = false;
		var re = new RegExp('^[a-zA-Z\\d\\._%-]{1,}@{1}[a-zA-Z\\d\\._%-]{1,}\\.{1}[a-zA-Z]{2,6}$');
		if (re.test(emailAddress)) {
			validity = true;
		}
		return validity;	
	}

	this._validateEmailMatch = function(email1, email2) { // Checks if to email addresses are the same
		var validity = false;
		var re = new RegExp('^[a-zA-Z\\d\\._%-]{1,}@{1}[a-zA-Z\\d\._%-]{1,}\\.{1}[a-zA-Z]{2,6}$');
		if (re.test(email1) && re.test(email2) && email1.match(email2)) {
			validity = true;
		}
		return validity;
	}

	this._validateLength = function(str, len) { // Checks a str length
		if(str.length > len) {
			validity = true;
		}
		return validity;
	}

	this._validateWebsite = function(websiteAddress) { // Checks if a given website address is valid
		var validity = false;
		var re = new RegExp('^[a-zA-Z\\d\\._%-]+\\.[a-zA-Z\\d\\._%-]+\.[a-zA-Z]{2,6}$');
	
		if (re.test(websiteAddress)) {
			validity = true;
		}
		return validity;
	}

	this._validatePhone = function(phoneNumber) { // Checks if a given phone number is valid
		if(phoneNumber.match(/\+/)) {
			return true; // let international numbers pass
		}
		var pn = phoneNumber.replace(/\D/g, '');
		var validity = false;
		var standardizedPhone = pn.substring(0,3) + '-' + pn.substring(3,6) + '-' + pn.substring(6,10);
		if (pn.length == 10) {
			standardizeFieldValue(this._field.id, standardizedPhone);
			validity = true;
		}
		return validity;	
	}

	this._validateCcExpiryDate = function(month, year) {  // Forces a credit card expiry date to be in the future, not more that 17 years
		var validity = false;
		var now = new Date();
		var curDate = new Date(now.getFullYear(), now.getMonth());
		var expDate = new Date(2000 + parseInt(year*1), parseInt(month*1)-1);
		var maxDate = new Date(curDate.getFullYear() + 17, curDate.getMonth());

		if (expDate.getTime() >= curDate.getTime()) {
			if (expDate.getTime() <= maxDate.getTime()) {
				validity = true;
			}
		}

		return validity;
	}

	this._validateCcNumber = function(cc) {
		var validity = false;
		var checksum = 0;
		var re = new RegExp('^\\d{14,16}$');
		if(re.test(cc)) {

			for(var i=(2-(cc.length % 2)); i<=cc.length; i+=2) {
				checksum = parseInt(checksum) + parseInt(cc.substring(i-1, i));
			}

			for(var i=(cc.length % 2) + 1; i<cc.length; i+=2) {
				var digit = parseInt(cc.substring(i-1, i)) * 2;
				if(digit<10) {
					checksum = parseInt(checksum) + parseInt(digit);
				} else {
					checksum = parseInt(checksum) + parseInt(digit-9);
				}
			}

			if((checksum % 10) == 0) {
				validity = true;
			} else {
				validity = false;
			}
		}
		
		return  validity;
	}

	this._validatePostal = function(postalCode) {
		var validity = false;
		var re = new RegExp('^[ABCEGHJKLMNPRSTVXY]{1}\\d{1}[a-zA-Z]{1}[-\\s]?\\d{1}[a-zA-Z]{1}\\d{1}$');

		if (re.test(postalCode.toUpperCase())) {
			standardizeFieldValue(this._field.id, postalCode.toUpperCase().replace(/[^A-Z0-9]/g, ''));
			validity = true;
		}

		return validity;
	}

	this._validatePostalProvince = function(validPostalCode, province) {
		var validity = false;
		var fsa = validPostalCode.toUpperCase().substring(0,1);
		var province_postals = new Array();
			province_postals['AB'] = new Array('T');
		 	province_postals['BC'] = new Array('V');
			province_postals['MB'] = new Array('R');
			province_postals['NB'] = new Array('E');
			province_postals['NL'] = new Array('A');
			province_postals['NS'] = new Array('B');
			province_postals['NT'] = new Array('X');
			province_postals['NU'] = new Array('X');
			province_postals['ON'] = new Array('K', 'L', 'M', 'N', 'P');
			province_postals['PE'] = new Array('C');
			province_postals['QC'] = new Array('G', 'H', 'J');
			province_postals['SK'] = new Array('S');
			province_postals['YT'] = new Array('Y');

		for(var i=0; i<province_postals[province].length; i++) {
			if(province_postals[province][i].match(fsa)) {
				validity = true;
			}
		}

		return validity;
	}

	this._validateFullName = function(nm) {
		var validity = false;
		var re = new RegExp('^[a-zA-Z]{1,}\\s*[a-zA-Z-\'\\.]{2,}\\s*[a-zA-Z-\'\\.\\s]*$');
		standardizeFieldValue(this._field.id, nm.replace(/\./g,""));
		if (re.test(nm)) {
			validity = true;
		}
		return validity;
	}

	this._validateNamePart = function(np) {
		var validity = false;
		var re = new RegExp('^[a-zA-Z\']{1,}\\s*[a-zA-Z-\'\\.{1,}\\s*[a-zA-Z-\'\\.\\s]*$');
		standardizeFieldValue(this._field.id, np.replace(/\./g,""));
		if (re.test(np)) {
			validity = true;
		}
		return validity;
	}

	this._validateNameInitial = function(ni) {
		var validity = false;
		var re = new RegExp('^[a-zA-Z]{1}\\.?$');
		standardizeFieldValue(this._field.id, ni.replace(/\./g,"").toUpperCase());
		if (re.test(ni)) {
			standardizeFieldValue(this._field.id, ni.toUpperCase());
			validity = true;
		}
		return validity;
	}

	this._validateCsc = function(csc) {
		var validity = false;
		var re = new RegExp('^\\d{3,4}$');
		if (re.test(csc)) {
			validity = true;
		}
		return validity;
	}

	this._validateAddress1 = function(address1) {
		var validity = false;
		var re = new RegExp('^[a-zA-Z0-9\\s\.-/,#]+$');
		
		// use standardizeFieldValue() to remove apostrophes and hyphens entered by the user
		address1 = address1.replace(/\'/g,"");
		address1 = address1.replace(/-/g," ");
		address1 = address1.replace(/\s{2,}/g," ");
		address1 = address1.replace(/\s$/,"");
		standardizeFieldValue(this._field.id, address1);
		
		if (re.test(address1)) {
			validity = true;
		}
		return validity;
	}

	this._validateAddress2 = function(address2) {
		var validity = false;
		var re = new RegExp('^[a-zA-Z0-9\\s\.-/,#]+$');
		
		// use standardizeFieldValue() to remove apostrophes and hyphens entered by the user
		address2 = address2.replace(/\'/g,"");
		address2 = address2.replace(/-/g," ");
		address2 = address2.replace(/\s{2,}/g," ");
		address2 = address2.replace(/\s$/,"");
		standardizeFieldValue(this._field.id, address2);
		
		if (re.test(address2)) {
			validity = true;
		}
		return validity;
	}

	this._validateCcPlaceName = function(placeName) {
		var validity = false;
		var re = new RegExp('^[a-zA-Z]{2,}[a-zA-Z\\d\\s\.]*$');

		// use standardizeFieldValue() to remove apostrophes and hyphens entered by the user
		placeName = placeName.replace(/\'/g,"");
		placeName = placeName.replace(/-/g," ");
		placeName = placeName.replace(/\s{2,}/g," ");
		placeName = placeName.replace(/\s$/,"");
		standardizeFieldValue(this._field.id, placeName);

		if (re.test(placeName)) {
			validity = true;
		}
		return validity;
	}
	
	this._validateYear = function(y, start, end) {
		var validity = false;
		var re = new RegExp('^\\d{4}$');
		if(!start) {
			start = 0000;
		}
		
		if(!end) {
			end = 2200; // some long-away futrue year
		}
		
		if(y>=start && y<= end && re.test(y)) {
			validity = true;
		}
		return validity;
	}
	
	this._validateDay = function(d) {
		var validity = false;
		var re = new RegExp('^\\d{1,2}$');
		
		if(re.test(d) && d>0 && d<32) {
			validity = true;
		}
		return validity;
	}
	
	this._validateMonth = function(m) {
		var validity = false;
		var re = new RegExp('^\\d{1,2}$');
		
		if(re.test(m) && m>0 && m<32) {
			validity = true;
		}
		return validity;
	}

	this._validateCheckbox = function(checkedState) {
		var validity = false;
	
		if(checkedState == true) {
			validity = true;
		}
		return validity;
	}

	this._validateSin = function(num) {
		var validity = false;
		var re = new RegExp('^[1245679]{1}\\d{2}[\\s-]?\\d{3}[\\s-]?\\d{3}$');
		
		if(re.test(num)) {
			var clean_num = num.replace('/\D/', '');
			var check_digit = clean_num.substring(8,9);
			var singles = new Array(clean_num.substring(0,1), clean_num.substring(2,3), clean_num.substring(4,5), clean_num.substring(6,7));
			var doubles = new Array(clean_num.substring(1,2), clean_num.substring(3,4), clean_num.substring(5,6), clean_num.substring(7,8));
			var sum = 0;
			var secondSum = 0;
			for(var i=0; i<singles.length; i++) {
				sum = parseInt(sum) + parseInt(singles[i]);
			}

			var dstr = '';
			var dsum = 0;
			
			for(var i=0; i<doubles.length; i++) {
				dstr += '' + doubles[i]*2;
			}

			var dsplit = dstr.split('');
			
			for(var i=0; i<dsplit.length; i++) {
				secondSum = parseInt(secondSum) + parseInt(dsplit[i]);
			}
			
			sum = parseInt(sum) + parseInt(secondSum);

			var check_sum = (10 - (sum % 10)) % 10;

			if(check_sum != check_digit) {
				validity = false;
			} else {
				validity = true;
			}
		}

		return validity;
	}
}


// Form Utility Functions

function standardizeFieldValue(fieldId, standardizedValue) {
	var f = document.getElementById(fieldId);
	f.value = standardizedValue;
}

function transformAccentChars(str) {
	var utfList = "\n";
	var c = 0;
	for (var utf=192; utf<=300; utf++) {
		utfList += utf.toString() + ":" + String.fromCharCode(utf.toString()) + "\t";
		c+=1;
		if(c==6) {
			utfList += "\n";
			c=0;
		}
	}
	alert(np + ' ' + utfList.toString());
}

function disableFormElement(elementId) {
	var fe = document.getElementById(elementId);
	fe.disabled = true;
	fe.className = fe.className.replace(/\s*disabled/g, '') + ' disabled';
}

function enableFormElement(elementId) {
	var fe = document.getElementById(elementId);
	fe.disabled = false;
	fe.className = fe.className.replace(/\s*disabled/g, '');
}

function removeFormElementCssErrorClass() {
	for(var i=0; i<document.forms.length; i++) {
		var f = document.forms[i];
		for (var e=0; e<f.elements.length; e++) {
			var elem = f.elements[e];
			if(elem.className.indexOf('error')>-1) {
				elem.className = elem.className.replace(/\s*error/, '');
			}
		}
	}
}

function resetTextarea(textAreaId, toReplace) {
	var ta = document.getElementById(textAreaId)
	if(ta.innerHTML) {
		ta.innerHTML = ta.innerHTML.replace(toReplace, '');
	}
}

