(function($){
	
	$.fn.validate_form = function(options){	
		$.fn.validate_form.defaults = {
			error_msg		: "",				/* "" | "custom message" 		*/
			highlight		: true,			/* false | true 					*/
			highlight_class: "err_hl",		/* highlight class 				*/
			error_type		: "inline",		/* popup | inline | none 		*/
			popup_class		: "err_popup",	/* popup class 					*/
			space_check		: false,			/* false | true					*/
			form_submit		: true,			/* false | true 					*/
			force_submit	: false,			/* false | true 					*/
			success			: function(){},/* success callback function 	*/
			error				: function(){}	/* error callback function 	*/
		};
		var o 		= $.extend({}, $.fn.validate_form.defaults, options);	
		var err_obj = new Array();
		var prev 	= new Object();


		return this.each(function(){

			$(this).submit(function(){
				return validate($(this));
			});
			
			$(":reset", $(this)).click(function(){				
				resetAll(this.form, err_obj, true);
			})
		});

		function validate(form_obj){
			if(prev){
				resetAll(prev.obj, prev.elems, true);
			}

			resetAll(form_obj, err_obj, false);
			
			err_obj = new Array();
			$("*[rel]", form_obj).each(function(){
				var me = $(this);
				if(me.offset().left != 0){
					switch(me.attr("rel")){
												
						case "check":
							var err_msg = "Please check this value.";
							if(!me.attr("checked")){
								err_obj.push(new Object({obj:me,msg:err_msg}));
								break;
							}
							break;
						case "multiselect":// GENERAL
							//alert(me.val());
							var err_msg = "Select any value.";
							if(me.val()==null){
								err_obj.push(new Object({obj:me,msg:err_msg}));
								break;
							}
							break;
						case "multiselect_limited":// CUSTOMIZED FOR LOCALSPIDER PROJECT
							var err_msg = "Select any value.";
							//alert(me.val());
							if(me.val()==null)
							{
								err_obj.push(new Object({obj:me,msg:err_msg}));
								break;
							}
							else
							{
								///customized for Local spyder
								//alert($jqobj("input[name='business_type']:checked").val());
								if($("input[name='business_type']:checked").val()=="enhanced")
								{
									if($(this).val().length>10)
									{
										 alert("You can select only 10 categories for  Enhanced business");
										err_obj.push(new Object({obj:me,msg:err_msg}));
										break;
									}
								}
								else
								{
									if($(this).val().length>1)
									{
										 alert("You can select only 1 category for Basic business");
										err_obj.push(new Object({obj:me,msg:err_msg}));
										break;
										}
									}
							}
							break;
						case "null": case "select":
							var rule = /.+/i;
							var err_msg = "Enter any value.";							
							doTest(me, rule, err_msg);
							break;
						
						case "email":
							var rule 	= /^[\w\-]+(\.[\w\-]+)*@([\w\-]+\.)+([a-z]{2,4})$/i;
							var err_msg = "Enter any valid Email.";
							
							doTest(me, rule, err_msg);
							break;
		
						case "url":
							var rule 	= /^(https?|ftp):\/\/(([\w-~]+)\.)+([a-z]{2,4})((\/(\w+)*)*|(\/*))([?\w-~=+&%#0-1])*$/i;
							var err_msg = "Enter any valid URL.";
							doTest(me, rule, err_msg);
							break;
							
						case "ip":
							var rule 	= /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/i;
							var err_msg = "Enter any valid IP.";
							doTest(me, rule, err_msg);
							break;
							
						case "number":
							var rule 	= /^\d+(\.\d+)?$/i;
							var err_msg = "Enter any valid Number.";
							doTest(me, rule, err_msg);
							break;
						
						default:						
							var rel 			= me.attr("rel");
							var val_type 	= rel.substr(0,2);
							var val_str 	= rel.substr(2,rel.length);							
							if(val_type == "r:"){
								rule = new RegExp(rel.substr(2,rel.length));
								var err_msg = "Enter any valid Value.";
								doTest(me, rule, err_msg);
							}else if(val_type == "f:"){
								rule = buildRegExp(rel.substr(2,rel.length));
								var err_msg = "Enter any valid Value.";
								doTest(me, rule, err_msg);
							}					
					}
				}
			});
			
			return finalAction(err_obj, form_obj);			
			
		}
		
		function doTest(me, rule, err_msg){
			if(!me.attr("disabled")){
				var extra 			= createObject(me.attr("opt"));
				var target_field 	= me.val();
				if(o.space_check){
					target_field = target_field.replace(/^(\s|\t)*/i, "");
					target_field = target_field.replace(/(\s|\t)*$/i, "");
				}
				
				if(!rule.test(target_field)){
					err_obj.push(new Object({obj:me,msg:err_msg}));
				}
				
				if(extra){
					var extra_msg = "";
					if(extra["compare"] && ($("*[name="+extra["compare"]+"]", me.attr("form")).val() != target_field)){
						extra_msg += " Comparison failed.";
					}	
					if(extra["min_len"] && (target_field.length < extra["min_len"])){					
						extra_msg += " Need atleast "+extra["min_len"]+" characters.";
					}
					if(extra["max_len"] && (target_field.length > extra["max_len"])){					
						extra_msg += " Maximum "+extra["max_len"]+" characters allowed.";
					}				
					var elems_len = err_obj.length - 1;
					if(extra_msg != ""){
						if(err_obj[elems_len]["obj"].attr("name") == me.attr("name")){
							err_obj[elems_len]["msg"] += extra_msg;
						}else{
							err_obj.push(new Object({obj:me,msg:err_msg+extra_msg}));
						}
					}				
				}
			}
		}
		
		function createObject(str){
			if(str){
				return eval("new Object("+str+")");
			}
			return "";
		}
		
		function buildRegExp(v){
			var val 	= v.split("");
			var re 	= "";
			for(i in val){			
				switch(val[i]){				
					case "9":	re += "\\d";	break;
					case "a":	re += "[a-z]";	break;
					case "A":	re += "[A-Z]";	break;
					case ".":	re += "\\.";	break;					
					default:re += new String("["+val[i]+"]");break;
				}						
			}			
			return new RegExp("^"+re+"$");
		}
		
		function highlightFields(obj_elems){
			for(i in obj_elems){
				if(o.highlight_class != ""){
					obj_elems[i]["obj"].addClass(o.highlight_class);
				}else{
					obj_elems[i]["obj"].css({
						backgroundColor:"#b5e1e9",
						border:"1px solid #8cc7d2"
					});
				}
			}
		}
		
		function showInlineError(obj_elems, obj){
			var msg = "";
			if(o.error_msg == ""){
				for(i in obj_elems){
					msg += (obj_elems[i]["obj"].attr("title") || obj_elems[i]["msg"]) + "<br />";
				}
			}
			
			msg = o.error_msg || msg;
			
			var target = $(".err_msg_cont",obj);					
			target.html("<div><div class=\"err_msg\">"+msg+"</div></div>");			
			$(target).slideDown();
		}
		
		function showPopupError(obj_elems){}
		
		function finalAction(obj_elems, form_obj){
			
			prev["obj"] 	= form_obj;
			prev["elems"] 	= obj_elems;
			
			if(obj_elems.length != 0){
				o.error();
				if(o.highlight){
					highlightFields(obj_elems);
				}
					
				switch(o.error_type){
					case "inline":
						showInlineError(obj_elems, form_obj);
						break;
						
					case "popup":
						showPopupError(obj_elems);
						break;	
											
					case "none":						
						break;
					
				}							
				return o.force_submit;
			}
			o.success();
			return o.form_submit;
		}
		
		function resetAll(obj, obj_elems, clear_error_msg){
			
			
			if(o.highlight){
				for(i in obj_elems){
					if(o.highlight_class){
						$("*[name="+obj_elems[i]["obj"].attr("name")+"]", obj).removeClass(o.highlight_class);
					}else{
						$("*[name="+obj_elems[i]["obj"].attr("name")+"]", obj).css({
							backgroundColor:"",
							border:""
						});
					}			
				}
			}
			if(clear_error_msg){
				switch(o.error_type){
					case "inline":
						$(".err_msg_cont", obj).slideUp();
						break;
					
					case "popup":						
						break;	
				}
			}
		}	
			
	}
})(jQuery);