(function( $ ){
	var methods = {
		stripSpaces: function(value){
			return value.replace(/[\s\xA0]+/g, '');
		},
		minCharCount: function(context, count){
			return !($(context).val().length < count);
		},
		maxCharCount: function(context, count){
			return ($(context).val().length <= count);
		},
		email: function(context){
			return /^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i.test(methods.stripSpaces($(context).val()));
		},
		matches: function(context, args){//[compare to, case sensitive]
			if(args[1]){//case sensitive
				return ($(context).val() == args[0])
			}
			return ($(context).val().toLowerCase() == args[0].toLowerCase());
		},
		required: function(context){
			switch($(context).attr("type")){
				case "text":
					return (methods.stripSpaces($(context).val()) != "");
				break;
				case "password":
					return (methods.stripSpaces($(context).val()) != "");
				break;
				case "checkbox":
					return $(context).attr("checked");
				break;
			}
			if($(context).get(0).tagName == "SELECT"){
				return ($(context).val() != "" && $(context).val() != "null");
			} else if($(context).get(0).tagName == "TEXTAREA"){
				return (methods.stripSpaces($(context).val()) != "");
			}
		},
		minAge: function(age,mm,dd,yyyy){//[min age,mm,dd,yyyy]
			var date = new Date((yyyy + age), mm, dd);
			if(((new Date).getTime() - date.getTime()) < 0) {
				return false;
			}
			return true;
		},
		fileExt: function(context, args){//[array of allowed file extensions]
			var ext = $(context).val().split('.').pop();
			var lower = ext.toLowerCase();
			for(var i=0;i<args.length;i++){
				if(args[i] == lower){
					return true;
				}
			}
			return false;
		},
		postal: function(context){ //a1a1a1 - whitespace and case insensitive
			return /^\s*[a-ceghj-npr-tvxy]\d[a-ceghj-npr-tv-z](\s)?\d[a-ceghj-npr-tv-z]\d\s*$/i.test(methods.stripSpaces($(context).val()));
		},
		zip: function(context){ //12345 -OR- 12345-6789
			return /^\d{5}([\-]\d{4})?$/.test(methods.stripSpaces($(context).val()));
		},
		postalZip: function(context){ //postal or zip code, either will pass
			return (methods.postal(context) || methods.zip(context));
		},
		phone: function(context, args){//[strict mask: bool]
			if(args[0]){
				var regex = new RegExp("[0-9][0-9][0-9]\-\[0-9][0-9][0-9]\-\[0-9][0-9][0-9][0-9]");
				return methods.stripSpaces($(context).val()).match(regex);
			} else {
				return /^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/.test(methods.stripSpaces($(context).val()));
			}
		},
		wordCount: function(context, args){//[return count, amount of words]
			var currentText = $(context).val();
			currentText = currentText.split("\n").join("%%");
			currentText = currentText.split(" ").join("%%");

			var wordArray = currentText.split("%%");
			var wordCount = 0;
			var a = wordArray.length;
			while(a--){
				if(wordArray[a] != ""){
					wordCount++;
				}
			}
			if(args[0]) return wordCount;
			if(wordArray[wordArray.length-1] == "" && wordCount >= args[1] && evt.keyCode != 8){
				return false;
			}
			return true;
		}
	}
	$.fn.brValidate = function(requirements) {
		var finalResults = [];
		var currentTest;
		for(var i=0;i<requirements.length;i++){
			currentTest = requirements[i];
			if(typeof currentTest == "string"){
				finalResults[i] = methods[currentTest]($(this));
			} else {
				for(var j in currentTest){
					finalResults[i] = methods[j](this, currentTest[j]);
				}
			}
		}
		return finalResults;
	};
	
	$.fn.validate = function(method){
		$(this).trigger("validate");
	}
	
	$.brValidateAge = function(age,mm,dd,yyyy){
		return methods.minAge(age,mm,dd,yyyy);
	}
	
})( jQuery );
