//copyright 2009 Wesley Bos

var frmvald_error = new Array();

jQuery.fn.parse = function() { //function that is being called by user
	parameter = $(this).attr("validation");
	if (typeof(parameter) == "undefined") {
		var returnval = "true";
	} else {
		var returnval = $.parse(this, parameter); // Call our own function where we validate the resource
	}
	if (returnval.match(/\x7C/)) {
		if ($.data($(this).parents("form").get(0), "showmessage")) {
			var message = returnval.split("|");
			if (message[0] == "false") {
				if ($(this).next().attr("class") == "error") {
					$(this).next().remove();
				}
				if (typeof $(this).attr("validatemsg") != "undefined" && $(this).attr("validatemsg").length) {
					$(this).after("<div class=\"error\">" + $(this).attr("validatemsg") + "</div>");
				} else {
					$(this).after("<div class=\"error\">" + message[1] + "</div>");
				}
			}
		}
		$(this).attr("validatestate", "false");
		if (typeof validate_error == "function") {
			validate_error($(this));
		}
	} else {
		if ($(this).next().attr("class") == "error") {
			$(this).next().remove();
		}
		$(this).attr("validatestate", "true");
		if (typeof validate_succes == "function") {
			validate_succes($(this));
		}
	}
};


jQuery.parse = function(object, parameter) {
	//Check if the user has custom error messages, if not create the standard messages
	if (typeof(frmvald_error["length:notNull"]) == "undefined") { frmvald_error["length:notNull"] = "This field must not be emtpy"; }
	if (typeof(frmvald_error["length:min"]) == "undefined") { frmvald_error["length:min"] = "This field must consist of at least <ammount> characters"; }
	if (typeof(frmvald_error["length:max"]) == "undefined") { frmvald_error["length:max"] = "This field may not consist of more then <ammount> characters"; }
	if (typeof(frmvald_error["value:min"]) == "undefined") { frmvald_error["value:min"] = "The value in this field must be higher then <value>"; }
	if (typeof(frmvald_error["value:max"]) == "undefined") { frmvald_error["value:max"] = "The value in this field must be lower then <value>"; }
	if (typeof(frmvald_error["email"]) == "undefined") { frmvald_error["email"] = "This field must be of the following syntax: x@x.xx"; }
	if (typeof(frmvald_error["compare"]) == "undefined") { frmvald_error["compare"] = "The values did not match"; }
	if (typeof(frmvald_error["pattern:digit"]) == "undefined") { frmvald_error["pattern:digit"] = "Only digits are allowed in this field"; }
	if (typeof(frmvald_error["pattern:digitDot"]) == "undefined") { frmvald_error["pattern:digitDot"] = "Only digits and dots are allowed in this field"; }
	if (typeof(frmvald_error["pattern:username"]) == "undefined") { frmvald_error["pattern:username"] = "The field may not consist of characters other then A-Z, a-z, 0-9 and the underscore"; }
	if (typeof(frmvald_error["pattern:default"]) == "undefined") { frmvald_error["pattern:default"] = "The field does not match the specified pattern"; }
	if (typeof(frmvald_error["radio"]) == "undefined") { frmvald_error["radio"] = "A radio buttons must be checked"; }
	if (typeof(frmvald_error["ajax"]) == "undefined") { frmvald_error["ajax"] = "This method must be valid"; }
	
	//Some variables we need to keep track of things
	var types = new Array();
	var at = 0;
	var count = 0;
	
	//Check if there is an , in the parameters line because this is what splits multiple parameters
	if (parameter.match(",")) {
		//We need to check if the "," is escaped by our custom escape character (because patterns use ",")
		while (parameter.indexOf(",", at) != -1) {
			var position = parameter.indexOf(",", at);
			//alert("position: " + position);
			//alert("at: "  + at);
			/*if the character before a "," is our costum escape character ("/") we need to do other stuff
			What we do in this part is, we create multiple parts of the orignal parameter filtering the "/" out of the parameter line
			*/
			if (parameter.charAt(position - 1) == "/") {
				//alert("1 - char = /");
				var substring1 = parameter.substring(at, (position - 1));
				types[count] = substring1;
				//alert("1 - types " + count + " :" + types[count]);
				if (parameter.indexOf(",", (position + 1)) != -1) {
					//alert("2 - another , is found");
					var nextposition = new Array()
					nextposition[0] = position;
					nextposition[1] = parameter.indexOf(",", (position + 1));
					var subcount = 1;
					while (parameter.charAt(nextposition[subcount] - 1) == "/") {
						//alert("2nd while started");
						var substring2 = parameter.substring(nextposition[subcount - 1], (nextposition[subcount] - 1));
						types[count] = types[count] + substring2;
						//alert("2 - types " + count + " :" + types[count]);
						subcount++;
						if (parameter.indexOf(",", (nextposition[subcount - 1] + 1)) != -1) {
							//alert("3 - another , is found");
							nextposition[subcount] = parameter.indexOf(",", (nextposition[subcount - 1] + 1));
							if (parameter.charAt(nextposition[subcount] - 1) != "/") {
								//alert("4 - char @ is not /");
								var substring3 = parameter.substring(nextposition[subcount - 1], nextposition[subcount]);
								types[count] = types[count] + substring3;
								//alert("4 - types " + count + " :" + types[count]);
							}
							at = nextposition[subcount] + 1;
						} else {
							//alert("3 - no , is found");
							if (parameter.charAt(nextposition[subcount - 1] - 1) == "/") {
								//alert("4 - char @ is a /");
								var substring3 = parameter.substring(nextposition[subcount - 1]);
								types[count] = types[count] + substring3;
								//alert("4 - types " + count + " :" + types[count]);
							}
							at = nextposition[subcount - 1] + 1;
							//alert("3 - at: " + at);
							break;
						}
					}
					if (parameter.charAt(nextposition[subcount - 1] - 1) != "/") {
						//alert("2 - comma was not escaped");
						var substring2 = parameter.substring(nextposition[subcount - 1], nextposition[subcount]);
						types[count] = types[count] + substring2;
						//alert("2 - types " + count + " :" + types[count]);
						at = nextposition[subcount - 1] + 1;
					}
				} else {
					//alert("2 - no , is found");
					var substring2 = parameter.substring(position);
					types[count] = types[count] + substring2;
					//alert("2 - types " + count + " :" + types[count]);
					at = position + 1;
				}
				count++;
			} else {
				//alert("1 - comma is not escaped");
				types[count] = parameter.substring(at, (position));
				//alert("1 - types " + count + " :" + types[count]);
				count++;
				at = position + 1;
			}
		}
		if (parameter.charAt(at - 2) != "/") {
			types[count] = parameter.substring(at);
			//alert("0 - types " + count + " :" + types[count]);
		}
	} else {
		types[0] = parameter;
	}
	//loop through all parameters stored in the array types
	for (var i = 0; i < types.length; i++) {
		//parameter variables are splitted by ":" so we need to split the variables that belong to a parameter
		if (types[i].match(":")) {
			parameters = types[i].split(":");
			var type = parameters[0];
			parameters.shift();
		} else {
			var type = types[i];
		}
		//If the paramter is length (length can have "notNull" as a variable but also min and max length ("1:2", min:max)
		if (type == "length") {
			switch(parameters[0]) {
				//if the variable is notNull
				case "notNull":
					//Check if the input field has a length of 0 and return an error message
					if ($(object).attr("value").length == 0) { return false  + "|" + frmvald_error["length:notNull"]; }
					break;
				default:
					//if both min and max length are specified we need to loop through them both
					for (var x = 0; x < parameters.length; x++) {
						switch(x) {
							//0 being the min length as min length is specified first in the variable of the parameter.
							case 0:
								//Check if the input field has a length less then the user specified parameter, then output an error message
								if ($(object).attr("value").length < parameters[x]) {
									frmvald_error["length:min"] = frmvald_error["length:min"].replace(/<ammount>/, parameters[x]);
									return false + "|" + frmvald_error["length:min"];
								}
								break;
							//1 being  the max length.
							case 1:
								//Check if the input field has a length greater then the user specified parameter, then output an error message
								if ($(object).attr("value").length > parameters[x]) { 
									frmvald_error["length:max"] = frmvald_error["length:max"].replace(/<ammount>/, parameters[x]);
									return false + "|" + frmvald_error["length:max"];
								}
								break;
						}
					}
					break;
			}
		//if the paramter is value (variables are min:max e.g. 1:4)
		} else if (type == "value") {
			//same loop as with length, loop through both min and max if both specified
			for (var x = 0; x < parameters.length; x++) {
				switch(x) {
					//In case of the min value
					case 0:
						//first make our object value an integer so we can referece it to a value, then check if the object value is lower then the specified value. If so, output an error message
						if (parseInt($(object).attr("value")) < parameters[x]) {
							frmvald_error["value:min"] = frmvald_error["value:min"].replace(/<value>/, parameters[x]);
							return false + "|" + frmvald_error["value:min"];
						}
						break;
					//In case of the max value
					case 1:
						//first make our object value an integer so we can referece it to a value, then check if the object value is higher then the specified value. If so, output an error message
						if (parseInt($(object).attr("value")) > parameters[x]) { 
							frmvald_error["value:max"] = frmvald_error["value:max"].replace(/<value>/, parameters[x]);
							return false + "|" + frmvald_error["value:max"];
						}
						break;
				}
			}
		//If the parameter is email (no variables possible)
		} else if (type == "email") {
			//Create the pattern of which an email must consist (x@x.xx being the minimal)
			var emailpattern = new RegExp(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/);
			//Check the value of the input field agains our pattern, if the pattern is not found in the input field output an error message
			if (!emailpattern.test($(object).attr("value"))) { return false + "|" + frmvald_error["email"]; }
		//If the paramter is compare (variable being the input field to compare it with. 2 possible types of variables; by id or by name. Id being indicated by a "#" e.g. #idname)
		} else if (type == "compare") {
			//check if the variable type is an id
			if (parameters[0].match("#")) {
				//check the input value against the input value specified in the variable. If they don't match output an error message
				if ($(object).attr("value") != $(parameters[0]).attr("value")) { return false + "|" + frmvald_error["compare"]; }
			} else {
				//check the input value against the input value specified in the variable. If they don't match output an error message
				if ($(object).attr("value") != $("input[name=" + parameters[0] + "]").attr("value")) { return false + "|" + frmvald_error["compare"]; }
			}
		//If the paramter is pattern (3 types of variables; digit (numbers only), username (Alphanumerical characters and the underscore) or a custom pattern ("," being escaped by "/" e.g. \\w{1/,3})
		} else if (type == "pattern") {
			switch(parameters[0]) {
				case "digit":
					//Create the patter to check if there are non digits in the input field
					var pattern = new RegExp(/\D/);
					//if the input field matched the pattern there are non-digits in the input field so an error message is given
					if (pattern.test($(object).attr("value"))) { return false + "|" + frmvald_error["pattern:digit"]; }
					break;
				case "digitDot":
					//Create the patter to check if there are non digits in the input field
					var pattern = new RegExp(/[-+]?([0-9]*\.)?[0-9]+/);
					//if the input field matched the pattern there are non-digits in the input field so an error message is given
					if (pattern.test($(object).attr("value"))) { 
						var newpattern = new RegExp(/[A-Za-z]/)
						if (newpattern.test($(object).attr("value"))) {
							return false + "|" + frmvald_error["pattern:digitDot"];
						}
					} else {
						return false + "|" + frmvald_error["pattern:digitDot"];
					}
					break;
				case "username":
					//Create a pattern to check if characters other then [A-Z a-z 0-9] and _ are in the input field
					var pattern = new RegExp(/\W/);
					//if the input field matched the pattern there are illegal characters in the input field so an error message is given
					if (pattern.test($(object).attr("value"))) { return false + "|" + frmvald_error["pattern:username"]; }
					break;
				default:
					//Create a new pattern consisting of the pattern given by the user.
					var pattern = new RegExp(parameters[0]);
					//check the pattern agains the input value, if pattern does not match output an error message
					if (!pattern.test($(object).attr("value"))) { return false + "|" + frmvald_error["pattern:default"]; }
					break;
			}
		} else if (type == "radio") {
			var radios = $("[name=" + $(object).attr("name") + "]");
			var checked = false;
			$(radios).each(function() {
				if ($(this).is(":checked")) checked = true;
			});
			if (!checked) { return false + "|" + frmvald_error["radio"]; }
		} else if (type == "ajax") {
			if ($(object).attr("validatestate") != "true") {
				$(object).trigger("change");
				$(object).trigger("blur");
				return false + "|" + frmvald_error["ajax"];
			}
		}
	}
	//if all goes well return true
	return "true";	
};

jQuery.fn.parseAll = function(showmessage) {
	var inputs = this.find(":input");
	var count = 0;
	for (var i = 0; i < inputs.length; i++) {
		$(inputs[i]).parse(showmessage);
		if ($(inputs[i]).attr("validation") == "ajax") $.data($(inputs[i]).get(0), "formsubmitted", "true");
		if ($(inputs[i]).attr("validatestate") == "true") {
			count++;
		} 
	}
	if (count == inputs.length) {
		return true;
	} else { 
		return false;
	}
};

jQuery.fn.initValidation = function(validateoptions) {
	if (typeof validateoptions == "undefined") validateoptions = {};
	if (typeof validateoptions.showmessage == "undefined") validateoptions.showmessage = true;
	if (typeof validateoptions.validateon == "undefined") validateoptions.validateon = "change";
	var inputs = this.find(":input");
	$.data($(this).get(0), "showmessage", validateoptions.showmessage);
	for (var i = 0; i < inputs.length; i++) {
		if (typeof($(inputs[i]).attr("validation")) != "undefined") {
			if ($(inputs[i]).attr("type") == "radio" && $(inputs[i]).attr("validation") != "ajax") $(inputs[i]).change(function() { $(this).parse() });
			if (validateoptions.validateon == "change" && $(inputs[i]).attr("validation") != "ajax") $(inputs[i]).change(function() { $(this).parse() });
			if (validateoptions.validateon == "blur" && $(inputs[i]).attr("validation") != "ajax") $(inputs[i]).blur(function() { $(this).parse() });
		}
	}
	$(this).submit(function() { return $(this).parseAll(); });
	return true;
}

