// Removes leading whitespaces
String.prototype.ltrim = function () {
	var re = /\s*((\S+\s*)*)/;
	return this.replace(re, "$1");
};

// Removes ending whitespaces
String.prototype.rtrim = function () {
	var re = /((\s*\S+)*)\s*/;
	return this.replace(re, "$1");
};

// Removes leading and ending whitespaces
String.prototype.trim = function () {
	return this.ltrim().rtrim();
};

// checks if an element exists in the array
Array.prototype.inArray = function (k) {
	for(var x = 0; x < this.length; x++) { if (this[x] == k) { return true; }}
	return false;
};

(function($) {

	$.fn.extend({

		form_validation: function(settings) {

			var settings = $.extend({
				ajax: false,
				messages: {
					required: 'Required Form Field.',
					invalid_email: 'Email Address is Invalid.',
					emailmx_failed: 'Unable to Verify Email Address.',
					blacklisted_email: 'Email Address is not Accepted.',
					invalid_naphone: 'Invalid North American Number.'
				}
			}, settings);

			var email_regex = /[a-zA-Z0-9!#$%&\'*+\/\=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/;
			var naphone_regex = /^1?([2-9][0-8][0-9])(?!55501)(?!\d11)([2-9][0-9]{6})\d*$/;
			var blacklist_regex = /^.*@(gmail.com|hotmail.com|yahoo.com|yahoo.ca|example.com)$/;


			var form = $(this);

			var elements = $(this).find(':input');
			var req_marked = new Array();

			init();

			function field_label(fld) {
				if (fld.title.length > 0)
					return fld.title;

				var labels = document.getElementsByTagName('label');

				for(var x = 0; x < labels.length; x++) {
					if (labels[x].htmlFor == fld.id)
						return labels[x].innerHTML;
				}

				return fld.name;
			}

			function field_label_obj(fld) {
				if (fld.title.length > 0)
					return fld.title;

				var labels = document.getElementsByTagName('label');

				for(var x = 0; x < labels.length; x++) {
					if (labels[x].htmlFor == fld.id)
						return labels[x];
				}

				return null;
			}

			function field_label_mark_req(fld) {

				var labels = document.getElementsByTagName('label');

				for(var x = 0; x < labels.length; x++) {
					if (((labels[x].htmlFor == fld.id && fld.type != 'radio') || (labels[x].htmlFor == fld.name.replace(/\[\]/, '') && fld.type == 'radio')) && !req_marked[fld.name.replace(/\[\]/, '')]) {
						req_marked[fld.name.replace(/\[\]/, '')] = true;
						return $(labels[x]).append('<span class="vfreqstar">*</span>');
					}
				}
			}

			function check_mxrecord(email) {
				if (window.XMLHttpRequest) {
					xhttp=new XMLHttpRequest();
				}
				else { // Internet Explorer 5/6
				  xhttp=new ActiveXObject("Microsoft.XMLHTTP");
				}

				xhttp.open("GET","/_inc/mxcheck.php?e=" + email,false);
				xhttp.send(null);

				this.mxvalid = (xhttp.responseText == 1);
				return this.mxvalid;
			}

			function init() {

				form
					.bind('submit',
						function(e) {
							return submit();
						});

				var spans = new Array();

				function get_err_element(cls, parent, order) {
					var err;
					if (document.getElementById(cls + '_' + order)) {
							err = document.getElementById(cls + '_' + order);
					}
					else {
						err = document.createElement('span');
						err.id = cls + '_' + order;
						if (parent) { $(parent).append(err); }
					}
					return err;
				}

				$.each(elements, function(x, element) {
					var classes = element.className.split(' ');

					var span = document.createElement('span');
					span.className = 'vferror';

					$(field_label_obj(element)).after(span);

					for(var z = 0; z < classes.length; z++) {

						var err = get_err_element(classes[z], span, x);

						if (classes[z] == 'vfreq') {

							field_label_mark_req(element);

							$(element)
								.bind('blur', function() {
									if (this.value.trim().length == 0) { $(err).html(settings.messages.required); }
									else { $(err).html(''); }
								});

						}

						if (classes[z] == 'vfemail') {

							$(element)
								.bind('blur', function() {
									if (this.value.trim().length > 0 && this.value.trim().match(email_regex) == null) { $(err).html(settings.messages.invalid_email); }
									else { $(err).html(''); }
								});

						}

						if (classes[z] == 'vfemailbl') {

							$(element)
								.bind('blur', function() {
									if (this.value.trim().length > 0 && this.value.trim().match(blacklist_regex) != null) { $(err).html(settings.messages.blacklisted_email); }
									else { $(err).html(''); }
								});

						}

						if (classes[z] == 'vfemailmx') {

							$(element)
								.bind('blur', function() {
									if (this.value.trim().length > 0 && this.value.trim().match(email_regex) == null) { $(err).html(settings.messages.invalid_email); }
									else if (this.value.trim().length > 0 && !check_mxrecord(this.value.trim())) { $(err).html(settings.messages.emailmx_failed); }
									else { $(err).html(''); }
								});

						}

						if (classes[z] == 'vfnaphonenum') {

							$(element)
								.bind('blur', function() {
									if (this.value.trim().length > 0 && this.value.replace(/[^0-9]/g, '').match(naphone_regex) == null) { $(err).html(settings.messages.invalid_naphone); }
									else { $(err).html(''); }
								});

						}

					}
				});

			}

			function submit() {

				var radioProcess = new Array();
				var invalid  = Array();
				var errors   = Array();

				$.each(elements, function(x, element) {
					var classes = element.className.split(' ');

					for(var z = 0; z < classes.length; z++) {
						if (element.type == 'radio' && !radioProcess.inArray(element.name) && classes[z] == 'vfreq') {
							radioProcess[radioProcess.length] = element.name;
							var found = false;
							for(var r = 0; r < elements.length; r++) { found = (found ? found : elements[r].type == 'radio' && elements[r].name == element.name && elements[r].checked); if (found) { break; } }
							if (!found) {
								invalid[invalid.length] = '&nbsp;&nbsp;&nbsp;&nbsp;&bull; ' + field_label(element).replace(/\*/, '');;
							}
						}
						if (element.type != 'radio' && element.value.trim().length == 0 && classes[z] == 'vfreq') // empty string and required
							invalid[invalid.length] = '&nbsp;&nbsp;&nbsp;&nbsp;&bull; ' + field_label(element).replace(/\*/, '').replace(/\:/, ' ');
						if (classes[z] == 'vfemail' && element.value.trim().length > 0 && element.value.trim().match(email_regex) == null)
							errors[errors.length] = field_label(element) + ' must be a valid email address.<br />';
						if (classes[z] == 'vfemailbl' && element.value.trim().length > 0 && element.value.trim().match(blacklist_regex) != null)
							errors[errors.length] = field_label(element) + ' is not accepted by our system, please use a different email address.<br />';
						if (classes[z] == 'vfemailmx' && element.value.trim().length > 0 && !check_mxrecord(element.value.trim()))
							errors[errors.length] = field_label(element) + ' cannot be verified with your domain<br /><br />Please try again.<br />';
						if (classes[z] == 'vfnaphonenum' && element.value.trim().length > 0 && element.value.replace(/[^0-9]/g, '').match(naphone_regex) == null)
							errors[errors.length] = field_label(element) + ' must be a valid north american phone number.<br />';

					}
				});

				if (invalid.length > 0 || errors.length > 0) {
					if (document.getElementById('vfdialog') == null) {
						var dialog = document.createElement('div');
						dialog.title = 'Form Submission';
						dialog.id = 'vfdialog';
						dialog.style.display = 'none';

						var body = document.getElementsByTagName('body');
						body[0].appendChild(dialog);
						jQuery("#vfdialog").dialog({
							bgiframe: true,
							modal: true,
							width: 400,
							buttons: {
								Ok: function() {
									jQuery(this).dialog('close');
								}
							},
							resizable: false
						});

					}

					var dialog = document.getElementById('vfdialog');

					dialog.innerHTML = ((invalid.length > 0 ? '<p>The following fields must be filled in:<br />' + invalid.join('<br />') + '</p>' : '') + (errors.length > 0 ? '<p>' + errors.join('<br />') + '</p>' : ''));
					jQuery("#vfdialog").dialog('open');
					invalid.length = 0;
					errors.length = 0;
					return false;
				}
				return true;

			}

		}

	});

})(jQuery);
