/**
 * File for a XProForm, XProFormAction and XProFormValidationAction pseudo namespaces
 *
 * @version	SVN: $Id: forms.js 8396 2007-08-29 14:58:08Z piotrd $
 */


/**
 * XProForm pseudo namespace
 */
function XProForm()
{
	// empty
}

/**
 * XProFormAction pseudo namespace
 */
function XProFormAction()
{
	// empty
}

/**
 * XProFormValidationAction pseudo namespace
 */
function XProFormValidationAction()
{
	// empty
	// should return XProCommon.createStatus()
}


/**
 * @type string
 */
XProForm.FORM_ERROR_MSG = "There was a problem processing the form.\nPlease correct all the fields in red.";


/**
 * Form on submit action
 *
 * @param form (object) form
 * @return boolean
 */
XProForm.onSubmit = function(form)
{
	if (XProForm.formValidator(form))
	{
		XProForm.customAction(form);

		XProCommon.disableSubmits();

		return true;
	}

	return false;
};


/**
 * Launches custom onSubmit action, if defined
 *
 * @param form (object) form
 * @return boolean
 */
XProForm.customAction = function(form)
{
	if (XProFormAction[form.id])
	{
		XProFormAction[form.id]();
	}

	return true;
}

/**
 * Launches custom onSubmit validation action, if defined
 *
 * @param form (object) form
 * @return boolean
 */
XProForm.customValidationAction = function(form)
{
	if (XProFormValidationAction[form.id])
	{
		return XProFormValidationAction[form.id]();
	}
	else
	{
		return XProCommon.createStatus(true, null);
	}
}


/**
 * Form validator
 *
 * @param form (object) form
 * @return boolean
 */
XProForm.formValidator = function(form)
{
	var is_form_error = false;
	var first_error_field = null;
	var status = null;

	for (var i = 0; i < form.elements.length; i++)
	{
		var field = form.elements[i];

		if (XProForm.fieldValidator(field, "all"))
		{
			is_form_error = true;

			if (null == first_error_field)
			{
				first_error_field = field;
			}
		}
	}

	status = XProForm.customValidationAction(form);

	if ( !status.correct)
	{
		is_form_error = true;
		if (null == first_error_field)
		{
			first_error_field = status.data;
		}
	}

	if (is_form_error)
	{
		XProForm.cleanIsValidated(form);
		if (null != first_error_field)
		{
			first_error_field.focus();
		}
		alert(XProForm.FORM_ERROR_MSG);
		return false;
	}

	return true;
};


/**
 * Field validator
 *
 * @param field (object) form field
 * @param mode (string|null) work mode: "all" checking all field, null checking only this field
 * @return boolean
 */
XProForm.fieldValidator = function(field, mode)
{
	var is_field_error = false;
	var field_value = new Array();
	var checked_number = 0;

	switch (field.tagName.toLowerCase())
	{
		case "input":
			if ("radio" == field.type || "checkbox" == field.type)
			{
				if ("true" != field.getAttribute("isValidated") || "all" != mode)
				{
					var multi_field = field.form.elements[field.name];

					for (var j = 0; j < multi_field.length; j++)
					{
						if ("all" == mode)
						{
							multi_field[j].setAttribute("isValidated", "true");
						}

						if (multi_field[j].checked)
						{
							if ("checkbox" == field.type)
							{
								checked_number++;
								field_value[field_value.length] = multi_field[j].value;
							}
							else
							{
								field_value = multi_field[j].value;
								break;
							}
						}
					}
				}
				else
				{
					return false;
				}
			}
			else if ("text" == field.type || "password" == field.type || "file" == field.type)
			{
				var trim = field.getAttribute("trim");
				if ( !XProCommon.isEmpty(trim))
				{
					XProForm.trimField(field, trim);
				}

				var convert = field.getAttribute("convert");
				if ( !XProCommon.isEmpty(convert))
				{
					XProForm.convertField(field, convert);
				}

				field_value = field.value;
			}
			else // button | hidden | image | submit | reset
			{
				return false;
			}
			break;

		case "textarea":
			field_value = field.value;
			break;

		case "select":
			// TODO: All values for select type multiple
			field_value = field.options[field.selectedIndex].value;
			break;

		default:
			return false;
	}

	if ("all" != mode)
	{
		if ( ("object" == typeof(field_value) && field_value.length < 1) || ("string" == typeof(field_value) && "" == field_value) )
		{
			if ("radio" == field.type || "checkbox" == field.type)
			{
				if (true == field.defaultChecked)
				{
					field.setAttribute("isNotEmptyValue", true);
				}
			}
			else if ("select" == field.tagName.toLowerCase())
			{
				for (var n = 0; n < field.options.length; n++)
				{
					if (true == field.options[n].defaultSelected)
					{
						field.setAttribute("isNotEmptyValue", true);
						break;
					}
				}
			}
			else if ( !XProCommon.isEmpty(field.defaultValue))
			{
				field.setAttribute("isNotEmptyValue", true);
			}

			if ( !field.getAttribute("isNotEmptyValue"))
			{
				return false;
			}
		}
		else
		{
			field.setAttribute("isNotEmptyValue", true);
		}
	}

	var required = field.getAttribute("plrequired");
	if ( !XProCommon.isEmpty(required) && "y" == required.toLowerCase())
	{
		if ( ("object" == typeof(field_value) && field_value.length < 1) || ("string" == typeof(field_value) && "" == field_value) )
		{
			is_field_error = true;
		}
	}

	if ( ("object" == typeof(field_value) && field_value.length > 1) || ("string" == typeof(field_value) && "" != field_value) )
	{
		var pattern = field.getAttribute("pattern");
		if ( !XProCommon.isEmpty(pattern))
		{
			var r = new RegExp(pattern, "m");

			if ("object" == typeof(field_value))
			{
				for (j = 0; j < field_value.length; j++)
				{
					if ( !r.test(field_value))
					{
						is_field_error = true;
						break;
					}
				}
			}
			else
			{
				if ( !r.test(field_value))
				{
					is_field_error = true;
				}
			}
		}

		if ("string" == typeof(field_value))
		{
			var min_length = field.getAttribute("minlength");
			if ( !XProCommon.isEmpty(min_length) && field_value.length < min_length)
			{
				is_field_error = true;
			}

			var max_length = field.getAttribute("maxlength");
			if ( !XProCommon.isEmpty(max_length) && field_value.length > max_length)
			{
				is_field_error = true;
			}

			var min = field.getAttribute("min");
			if ( !XProCommon.isEmpty(min) && +field_value < +min)
			{
				is_field_error = true;
			}

			var max = field.getAttribute("max");
			if ( !XProCommon.isEmpty(max) && +field_value > +max)
			{
				is_field_error = true;
			}

			var date = field.getAttribute("date");
			if ( !XProCommon.isEmpty(date) && !XProForm.checkDate(field, date))
			{
				is_field_error = true;
			}
		}
		else if ("checkbox" == field.type)
		{
			var last_check_number = +field.getAttribute("lastCheckNumber");

			var min_checked = field.getAttribute("minchecked");
			if ( !XProCommon.isEmpty(min_checked) && +checked_number < +min_checked && last_check_number >= +min_checked)
			{
				is_field_error = true;
			}

			var max_checked = field.getAttribute("maxchecked");
			if ( !XProCommon.isEmpty(max_checked) && +checked_number > +max_checked)
			{
				is_field_error = true;
			}

			if (+checked_number > last_check_number)
			{
				field.setAttribute("lastCheckNumber", checked_number);
			}
		}
	}

	if (field.disabled && true == field.disabled)
	{
		is_field_error = false;
	}

	XProForm.switchFieldTip(field, is_field_error);

	return is_field_error;
};


/**
 * Return real field id
 *
 * @private
 * @param field (object) form field
 * @return string
 */
XProForm.getFieldId = function(field)
{
	var id = field.id;

	if ("input" == field.tagName.toLowerCase() && ("radio" == field.type || "checkbox" == field.type))
	{
		id = id.substring(0, id.lastIndexOf("-"));
	}

	return id;
};


/**
 * @param field (object) form field
 * @param method (string)
 * @return void
 */
XProForm.trimField = function(field, method)
{
	switch (method.toLowerCase())
	{
		case "left":
			field.value = field.value.leftTrim();
			break;
		case "right":
			field.value = field.value.rightTrim();
			break;
		case "both":
			field.value = field.value.trim();
			break;
		case "all":
			field.value = field.value.allTrim();
			break;
		default:
			alert("Unknown trim method '" + method + "' for field '" + field.name + "'");
			break;
	}
};


/**
 * @param field (object) form field
 * @param method (string)
 * @return void
 */
XProForm.convertField = function(field, method)
{
	switch (method.toLowerCase())
	{
		case "upper":
			field.value = field.value.toUpperCase();
			break;
		case "lower":
			field.value = field.value.toLowerCase();
			break;
		default:
			alert("Unknown convert method '" + method + "' for field '" + field.name + "'");
			break;
	}
};


/**
 * @param field (object) form field
 * @param date_format (string)
 * @return boolean
 */
XProForm.checkDate = function(field, date_format)
{
	var date_pieces = null;

	switch (date_format)
	{
		case "YYYY-MM-DD":
			date_pieces = field.value.split("-");
			break;

		default:
			alert("Unknown checkDate date_format '" + date_format + "' for field '" + field.name + "'");
			break;
	}

	date_pieces[1]--;

	var date = new Date(date_pieces[0], date_pieces[1], date_pieces[2]);

	if (date_pieces[0] != date.getFullYear()
			|| date_pieces[1] != date.getMonth()
			|| date_pieces[2] != date.getDate())
	{
		return false;
	}

	return true;
};


/**
 * Checks if supplied number passes Luhn
 *
 * @param number (string) number to check
 * @return boolean
 */
XProForm.checkLuhn = function(number)
{
	var sum = 0;
	var double_this_digit = false;

	for (var n = number.length - 1; n >= 0; n--)
	{
		var digit = +number.charAt(n);

		if (double_this_digit)
		{
			digit *= 2;

			if (digit > 9)
			{
				digit -= 9;
			}
		}

		sum += digit;
		double_this_digit = !double_this_digit;
	}

	return 0 == sum % 10;
};

/**
 * Switch field tip / error tip text and color.
 *
 * @private
 * @param field (object) form field
 * @param is_error (boolean)
 * @param extra_error_tip (string) optional
 * @return void
 */
XProForm.switchFieldTip = function(field, is_error, extra_error_tip)
{
	var tip_box = null;
	var tip_name_suffix = null;
	var group_id = field.getAttribute("group_id");

	if ( !XProCommon.isEmpty(group_id))
	{
		tip_name_suffix = group_id;
	}
	else
	{
		tip_name_suffix = XProForm.getFieldId(field);
	}

	tip_box = document.getElementById("tip-" + tip_name_suffix);

	if (null == tip_box)
	{
		return;
	}

	if (is_error)
	{
		with (field.style)
		{
			borderWidth = "1px";
			borderStyle = "solid";
			borderColor = "red";
		}

		tip_box.className = "form-field-error";

		var error_tip = field.getAttribute("errortip");

		if ( !XProCommon.isEmpty(extra_error_tip))
		{
			tip_box.innerHTML = extra_error_tip;
		}
		else if (XProCommon.isEmpty(error_tip))
		{
			tip_box.innerHTML = "&nbsp;";
		}
		else
		{
			tip_box.innerHTML = error_tip;
		}
	}
	else
	{
		with (field.style)
		{
			borderWidth = "";
			borderStyle = "";
			borderColor = "";
		}

		tip_box.className = "form-field-tip";

		var tip = field.getAttribute("tip");
		if (XProCommon.isEmpty(tip))
		{
			tip_box.innerHTML = "&nbsp;";
		}
		else
		{
			tip_box.innerHTML = tip;
		}
	}
};


/**
 * Clean attributes isValidated added to checkbox and radio field
 *
 * @private
 * @param form (object) form
 * @return void
 */
XProForm.cleanIsValidated = function(form)
{
	var fields = form.getElementsByTagName("input");

	for (var i = 0; i < fields.length; i++)
	{
		if ("radio" == fields[i].type || "checkbox" == fields[i].type)
		{
			fields[i].setAttribute("isValidated", "false");
		}
	}
};


/**
 * Display error message. Set focus in first field with error
 *
 * @param id (string) field id
 * @return void
 */
XProForm.onFormError = function(id)
{
	alert(XProForm.FORM_ERROR_MSG);

	var field = document.getElementById(id);
	if (null != field)
	{
		field.focus();
		return;
	}

	var fields = document.getElementsByTagName('input');
	for (var i = 0; i < fields.length; i++)
	{
		if ( ("radio" == fields[i].type || "checkbox" == fields[i].type) && -1 != fields[i].id.indexOf(id, 0) )
		{
			fields[i].focus();
			return;
		}
	}
};


/**
 * Set cursor in the first field in the first form on page
 *
 * @return void
 */
XProForm.setCursorInFirstField = function()
{
	for (var n = 0; n < document.forms.length; n++)
	{
		if ("fast_search" == document.forms[n].id || "select_account_form" == document.forms[n].id)
		{
			continue;
		}

		for (var m = 0; m < document.forms[n].elements.length; m++)
		{
			if ("submit" != document.forms[n].elements[m].type)
			{
				try
				{
					document.forms[n].elements[m].focus();
				}
				catch (e)
				{
					return;
				}

				return;
			}
		}
	}
};

/**
 * Displays yes/no confirmation window with given question
 *
 * @param string text Question to display
 * @return boolean True if user clicked 'Yes', false otherwise
 */
XProForm.confirmWindow = function(text)
{
	if ("" == text)
	{
		text = "Are you sure you want to submit the form?";
	}

	return confirm(text);
};

/**
 * @param node button_node
 */
XProForm.cloneFormNode = function(button_node)
{
	var node = null;

	for (n in button_node.parentNode.childNodes)
	{
		node = button_node.parentNode.childNodes[n];

		if (1 == node.nodeType)
		{
			break;
		}
	}

	if (null == node)
	{
		return;
	}

	var br_node = document.createElement("br");

	button_node.parentNode.appendChild(br_node);
	button_node.parentNode.insertBefore(br_node, button_node);

	var new_node = node.cloneNode(false);

	new_node.setAttribute("plrequired", "no");
	new_node.value = "";

	new_node.style.borderWidth = "";
	new_node.style.borderStyle = "";
	new_node.style.borderColor = "";

	new_node.name = button_node.form.id + "[" + button_node.getAttribute("clone_name") + "][]";

	button_node.parentNode.appendChild(new_node);
	button_node.parentNode.insertBefore(new_node, button_node);

	new_node.focus();

	if (XProCommon.ie)
	{
		button_node.focus();
		new_node.focus();
	}
};