// util
if(typeof(util)=="undefined")
{
	var util = new Object();
}

util.form = new Object();

util.form.checkDate = function(str)
{
	var d=str.Trim();
	if(d=='')
	{
		return(true);
	}
	
	var m_names = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

	// get separator
	var separator='';
	var separatorsList=new Array("-", "/", " ");
	
	for(var i=0; i<separatorsList.length; i++)
	{
		if(d.indexOf(separatorsList[i], 0)!=-1)
		{
			separator=separatorsList[i];
			break;
		}
	}
	
	// if separator is SPACE, then the date should be dd {mm} yyyy, where {mm} is the
	// 3-letters short for the month name
	if(separator=="")
	{
		return(false);
	}
	else
	{
		if(isNaN(Date.parse(d)))
		{
			return(false);
		}
	}

	// check if the entered date is the same as the javascript date.
	var dateArray=util.string.stringToArray(d, separator, false);

	var date=new Date(d);
	var dateDD, dateMM;
	if(separator==" ")
	{
		var m;
		dateArray[1] = dateArray[1].toLowerCase();
		for(m=0; (m<m_names.length) && (m_names[m].toLowerCase()!=dateArray[1]); m++);
		if(m==m_names.length)
		{
			return(false);
		}
		dateMM = m + 1;
		dateDD = parseInt(util.string.leftTrimChar(dateArray[0], "0"));
	}
	else
	{
		dateDD=parseInt(util.string.leftTrimChar(dateArray[1], "0"));
		dateMM=parseInt(util.string.leftTrimChar(dateArray[0], "0"));
	}
	var dateYYYY=parseInt(dateArray[2]);
	if(dateYYYY>9999)
	{
		return(false);
	}
	if((dateMM!=(date.getMonth()+1)) || (dateDD!=date.getDate()) || (dateYYYY!=date.getFullYear()))
	{
		return(false);
	}
	return(true);
};

util.form.checkEmail = function(str)
{
	var pattern =  /^[a-z]([\.\-\_]{0,}[a-z_0-9]|[a-z_0-9]\.[a-z_0-9])+@([a-z0-9]|[a-z0-9][\.\-][a-z0-9])+\.[a-z]{2,}$/i
  return pattern.test(str)
};

util.form.check = function(field, fieldName, empty, type, min, max, message, focusField)
{
	if(field==null)
	{
		return(true);
	}
	var str = field.value;
	if(focusField!=null)
	{
		field = focusField;
	}
	if(empty && ((str=="") || (str==null)))
	{
		FormUtilsShowMessage("Please enter a value in the \"" + fieldName + "\" field.", message);
		if(field.type!="hidden")
		{
			field.focus();
		}
		return(false);
	}
	
	switch(type.toLowerCase())
	{
		case "string":
			if(empty || (!empty && str!=""))
			{
				if((min!=null) && (str.length<min))
				{
					FormUtilsShowMessage("Please enter at least " + min + " characters in the \"" +
						fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			if((max!=null) && (str.length>max))
			{
				FormUtilsShowMessage("Please enter at most " + max + " characters in the \"" +
					fieldName + "\" field.\r\n(Current count: " + str.length + " characters)", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
				return(false);
			}
			break;
		case "int":	
			if(empty || (!empty && str!=""))
			{
				if(isNaN(parseInt(str)))
				{
					FormUtilsShowMessage("Please enter an integer value in the \"" + fieldName +
						"\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				str = parseInt(str);
				if((min!=null) && (str<min))
				{
					FormUtilsShowMessage("Please enter a value superior to " + min + 
						" in the \"" + fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				if((max!=null) && (str>max))
				{
					FormUtilsShowMessage("Please enter a value inferior to " + max + 
						" in the \"" + fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "float":	
			if(empty || (!empty && str!=""))
			{
				if(isNaN(parseFloat(str)))
				{
					FormUtilsShowMessage("Please enter an float value in the \"" + fieldName +
						"\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				str = parseFloat(str);
				if((min!=null) && (str<min))
				{
					FormUtilsShowMessage("Please enter a value superior to " + min + 
						" in the \"" + fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				if((max!=null) && (str>max))
				{
					FormUtilsShowMessage("Please enter a value inferior to " + max + 
						" in the \"" + fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "date":
			if(min!=null)
			{
				min = util.string.dateRendererEx(min);
			}
			if(max!=null)
			{
				max = util.string.dateRendererEx(max);
			}
			if(empty || (!empty && str!=""))
			{
				if(!util.form.checkDate(str))
				{
					FormUtilsShowMessage("Please enter a valid date in the \"" +
						fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				str = Date.parse(str);
				if((min!=null) && (str<Date.parse(min)))
				{
					FormUtilsShowMessage("Please enter a date past or equal to " + min +
						" in the \"" + fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				if((max!=null) && (str>Date.parse(max)))
				{
					FormUtilsShowMessage("Please enter a date prior or equal to " + max +
						" in the \"" + fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "email":
			if(empty || (!empty && str!=""))
			{
				if(!util.form.checkEmail(str))
				{
					FormUtilsShowMessage("Please enter a valid e-mail address in the \"" +
						fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "pattern":
			if(empty || (!empty && str!=""))
			{
				if(!min.test(str))
				{
					FormUtilsShowMessage("Please enter a valid " + max + " in the \"" +
						fieldName + "\" field.", message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
	}
	return(true);
};

util.form.checkRadio = function(field, fieldName, message)
{
	if(field==null)
	{
		return(true);
	}
	for(var i=0; ((i<field.length) && (!field[i].checked)); i++);
	if(i==field.length)
	{
		FormUtilsShowMessage("Please select an option for \"" + fieldName + "\"", message);
		return(false);
	}
	return(true);
};

util.form.checkSelect = function(field, fieldName, emptyValue, message)
{
	if(field==null)
	{
		return(true);
	}
	var selIn = field.selectedIndex;
	var ok = true;
	if(selIn==-1)
	{
		ok = false;
	}
	else
	{
		if(emptyValue!=null)
		{
			if(field.options[selIn].value==emptyValue)
			{
				ok = false;
			}
		}
	}
	if(!ok)
	{
		FormUtilsShowMessage("Please select a value for \"" + fieldName + "\"", message);
		if(field.type!="hidden")
		{
			field.focus();
		}
	}
	return(ok);
}

function FormUtilsShowMessage(str, message)
{
	if(message==null)
	{
		alert(str);
	}
	else
	{
		alert(message);
	}
}

util.form.getListItemName = function(options, value)
{
	var name;
	for(var i=0; i<options.length; i++)
	{
		if(options[i].value==value)
		{
			name = options[i].text;
			break;
		}
	}
	if(name==null)
	{
		name = "[undefined]";
	}
	return(name);
};

util.form.getListItemIndex = function(options, value)
{
	var i;
	for(i=0; i<options.length; i++)
	{
		if(options[i].value==value)
		{
			break;
		}
	}
	if(i==options.length)
	{
		i = -1;
	}
	return(i);
};

util.form.setRadio = function(fields, value)
{
	// finds the radio button inside a radio buttons list and checks the selected one. 
	// Returns {true} if the value was found, {false} otherwise.
	if(fields.length==null)
	{
		if(fields.value==value)
		{
			fields.checked = true;
			return(true);
		}
		return(false);
	}
	for(var i=0; i<fields.length; i++)
	{
		if(fields[i].value==value)
		{
			fields[i].checked = true;
			return(true);
		}
	}
	return(false);
};

util.form.makeRequest = function(forme)
{
	var str = new Array();
	var value, elt, history = new Object();
	for(var i=0; i<forme.elements.length; i++)
	{
		elt = forme.elements[i];
		if(elt.disabled)
		{
			continue;
		}
		if(history[elt.name]!=null)
		{
			continue;
		}
		history[elt.name] = 1;
		value = util.string.urlEncode(elt.name) + "=" ;
		switch(elt.tagName.toLowerCase())
		{
			case "input":
			{
				switch(elt.type.toLowerCase())
				{
					case "radio":
					{
						if(elt.checked)
						{
							str.push(value + util.string.urlEncode(elt.value));
						}
						break;
					}
					case "checkbox":
					{
						if(elt.checked)
						{
							var cV = elt.value;
							if(cV=="")
							{
								cV = "on";
							}
							str.push(value + util.string.urlEncode(cV));
						}
						break;
					}
					default:
					{
						str.push(util.string.urlEncode(elt.name) + "=" + util.string.urlEncode(elt.value));
						break;
					}
				}
				break;
			}
			case "select":
			{
				var sV = new Array();
				for(var i=0; i<elt.options.length; i++)
				{
					if(elt.options[i].selected)
					{
						sV.push(elt.options[i].value);
					}
				}
				str.push(util.string.urlEncode(elt.name) + "=" + util.string.urlEncode(sV.join(",")));
				break;
			}
			default:
			{
				str.push(util.string.urlEncode(elt.name) + "=" + util.string.urlEncode(elt.value));
				break;
			}
		}
	}
	return(str.join("&"));
};

util.form.validator = function(field, fieldName, empty, type, min, max, message, focusField)
{
	this.validate = function()
	{
		return(util.form.check(field, fieldName, empty, type, min, max, message, focusField));
	};
};

util.form.fileValidator = function(field, fieldName, typesList)
{
	this.validate = function()
	{
		var fileName = field.value;
		if(fileName=="")
		{
			return(true);
		}
		fileName = fileName.split(".");
		if(fileName.length<2)
		{
			alert("You are trying to upload a file for \"" + fieldName + "\" with no extension. \r\n" +
				"Please add an extension to your file Name or select another file.");
			field.select();
			field.focus();
			return(false);
		}
		var ext = fileName.pop().toLowerCase();
		if(util.string.arrayScan(typesList, ext)==-1)
		{
			var messageTypes = new Array();
			for(var i=0; i<typesList.length; i++)
			{
				messageTypes.push("*." + typesList[i]);
			}
			alert("Please enter a file for \"" + fieldName + "\" with one of the following extension(s) only:\r\n\r\n" +
				messageTypes.join(", "));
			field.select();
			field.focus();
			return(false);
		}
		return(true);
	};
};

util.form.radioValidator = function(field, fieldName, message)
{
	this.validate = function()
	{
		return(util.form.checkRadio(field, fieldName, message));
	};
};

util.form.uniqueValidator = function(field, fieldName, valuesList, message)
{
	this.validate = function()
	{
		var v = field.value;
		if(v=="")
		{
			return(true);
		}
		if(util.string.arrayScan(valuesList, v)>=0)
		{
			if(message==null)
			{
				message = "Value in field \"" + fieldName + "\" must be different than any of the following values:\r\n" +
					valuesList.join(",");
			}
			FormUtilsShowMessage(message);
			return(false);
		}
		return(true);
	};
};

util.form.selectValidator = function(field, fieldName, emptyValue, message)
{
	this.validate = function()
	{
		return(util.form.checkSelect(field, fieldName, emptyValue, message));
	};
};

util.form.customValidator = function(condition, message)
{
	this.validate = function()
	{
		if(!condition)
		{
			FormUtilsShowMessage(message);
		}
		return(condition);
	};
};

util.form.selectEdValidator = function(list, fieldName, required, voidValue, message)
{
	this.validate = function()
	{
		if(list.disabled)
		{
			return(true);
		}
		var o = list.getValue();
		var v = o.value;
		var t = o.text;
		if((v==null) || (v==voidValue))
		{
			if(required)
			{
				if(message==null)
				{
					message = "Please select a value for \"" + fieldName + "\"";
				}
				FormUtilsShowMessage(message);
				return(false);
			}
			if((t=="") && (!list.allowNewValues))
			{
				if(message==null)
				{
					message = "Please select a value for \"" + fieldName + "\" from the list or enter your own value.";
				}
				FormUtilsShowMessage(message);
				return(false);
			}
		}
		return(true);
	};
};

util.form.scanValidators = function(validators)
{
	var v;
	for(var i=0; i<validators.length; i++)
	{
		if(!validators[i].validate())
		{
			return(false);
		}
	}
	return(true);
};

util.form.getEltValue = function(elt)
{
	var val = null;
	switch(elt.tagName.toLowerCase())
	{
		case "textarea":
		{
			val = elt.value;
			break;
		}
		case "select":
		{
			var a = new Array();
			for(var i=0; i<elt.options.length; i++)
			{
				if(elt.options[i].selected)
				{
					a.push(elt.options[i].value);
				}
			}
			val = a.join(",");
			break;
		}
		case "input":
		{
			switch(elt.type)
			{
				case "checkbox":
				{
					val = elt.checked;
					break;
				}
				case "file":
				{
					val = elt.value;
					break;
				}
				case "hidden":
				{
					val = elt.value;
					break;
				}
				case "password":
				{
					val = elt.value;
					break;
				}
				case "text":
				{
					val = elt.value;
					break;
				}
				case "radio":
				{
					var forme = elt.form;
					var l = forme[elt.name].length;
					for(var i=0; i<l; i++)
					{
						if(forme[elt.name][i].selected)
						{
							val = forme[elt.name][i].value;
							break;
						}
					}
					break;
				}
			}
			break;
		}
	}
	return(val);
};

util.form.getFormsDefaultValues = function()
{
	ctx.formDefaultValues = new Object();
	var fL = document.forms.length;
	var l, o, forme, val;

	for(var i = 0; i<fL; i++)
	{
		forme = document.forms[i];
		o = new Object();
		l = forme.elements.length;
		for(var j=0; j<l; j++)
		{
			val = util.form.getEltValue(forme.elements[j]);
			if(val!=null)
			{
				o[forme.elements[j].name] = val;
			}
		}
		ctx.formDefaultValues[forme.name] = o;
	}
};


util.form.hasChanges = function(forme, skipElements)
{
	if(skipElements==null)
	{
		skipElements = new Array();
	}
	var o = new Object();
	var l = forme.elements.length;
	var elt;
	var names = new Array();
	for(var i=0; i<l; i++)
	{
		elt = forme.elements[i];
		val = util.form.getEltValue(elt);
		if(val!=null)
		{
			o[elt.name] = val;
			names.push(elt.name);
		}
	}
	
	var hasChanged = false;
	var dNames = new Array();
	var dO = ctx.formDefaultValues[forme.name];
	for(eltName in o)
	{
		if(skipElements.indexOf(eltName)==-1)
		{
			if(o[eltName]!=dO[eltName])
			{
/*
				alert("forme: " + forme.name + "\r\n" + eltName + " was " + dO[eltName] + ", is " + o[eltName] +
					"\r\n" + forme[eltName].outerHTML);
*/
				hasChanged = true;
				break;
			}
		}
		dNames.push(eltName);
	}
	if(!hasChanged)
	{
		names = names.sort();
		dNames = dNames.sort();
		if(names.length!=dNames.length)
		{
			// NOTE: getting here means that either the form controls have changed indeed, or that more than one control
			// with the same name exist within the same form.
			//alert("Form name: " + forme.name + "\r\nDefault controls: " + dNames + "\r\nActual controls: " + names);
			hasChanged = true;
		}
		else
		{
			for(var i=0; i<names.length; i++)
			{
				if(names[i]!=dNames[i])
				{
					hasChanged = true;
					break;
				}
			}
		}
	}
	return(hasChanged);
};

util.form.haveChanges = function()
{
	var fL = document.forms.length;
	var haveChanges = false;
	for(var i=0; i<fL; i++)
	{
		if(util.form.hasChanges(document.forms[i]))
		{
			haveChanges = true;
			break;
		}
	}
	return(haveChanges);
};
