/*
 * This function is used from list of records to (de)select all records.
 * It (un)checks all checkboxes on the first form of the page based on the
 * setting of the checkbox with name 'allBox'.
 */
function checkAll() {
	var formIndex = 0;
	if (arguments.length > 0) {
		formIndex = arguments[0];
	}
	var form = document.forms[formIndex];
	var checkAll = form.allBox;
	
	for (var i = 0; i < form.elements.length; i++) {
		var field = form.elements[i];
		if (field.type == 'checkbox') {
			field.checked = checkAll.checked;
		}
	}
}

// Do not polute global namespace. Put all yawaf related data in this object.
var yawaf = new Object();

/* ************************************************************************ *
 *                                 Messages                                 *
 * ************************************************************************ */
yawaf.messages = new Object();

yawaf.messages.fields = new Object();
yawaf.messages.fields.password_check = "Password again";

yawaf.messages.fields["origin.country"] = "Start - Land";
yawaf.messages.fields["origin.postal_code"] = "Start - PLZ";
yawaf.messages.fields["origin.city"] = "Start - Ort";
yawaf.messages.fields["destination.country"] = "Ziel - Land";
yawaf.messages.fields["destination.postal_code"] = "Ziel - PLZ";
yawaf.messages.fields["destination.city"] = "Ziel - Ort";

yawaf.messages.required = "{0} is required";
yawaf.messages.invalidInt = "{0}: integer expected";
yawaf.messages.invalidFloat = "{0}: float expected";
yawaf.messages.minlength = "{0} must be at least {2} characters long";
yawaf.messages.lte = "{0} must be less then or equal to {2}";
yawaf.messages.same_passwords = "passwords do not match";

/* ************************************************************************ *
 *                                Validators                                *
 * ************************************************************************ */

yawaf.validators = new Object();

yawaf.validators.isEmpty = function(value) {
	return (value == null) || (value.length == 0);
}

yawaf.validators.required = function(field, value) {
	var result = "";
	
	if (this.isEmpty(value)) {
		result = yawaf.formatMessage(yawaf.messages.required, field, value);
	}

	return result;
}

yawaf.validators.isInt = function(field, value) {
	var result = "";
	
	if (!value.match(/^[+-]?[0-9]+$/)) {
		result = yawaf.formatMessage(yawaf.messages.invalidInt, field, value);
	}
	
	return result;
}

yawaf.validators.isFloat = function(field, value) {
	var result = "";
	
	if (!value.match(/^[+-]?([0-9]+([.][0-9]*)?)|([.][0-9]+)$/)) {
		result = yawaf.formatMessage(yawaf.messages.invalidFloat, field, value);
	}
	
	return result;
}

yawaf.validators.minlength = function(field, value, len) {
	var result = "";
	if (value && value.length < len) {
		result = yawaf.formatMessage(yawaf.messages.minlength, field, value, len);
	}
	return result;
}

yawaf.validators.isLTE = function(field, value, max) {
	var result = "";
	
	if (value > max) {
		result = yawaf.formatMessage(yawaf.messages.lte, field, value, max);
	}
	
	return result;
}
		

yawaf.validators.same_passwords = function(form) {
	var result = "";

	if (form.getValue("password") != form.getValue("password_check")) {
		result = yawaf.formatMessage(yawaf.messages.same_passwords);
		form.setFieldError("password", result);
		form.setFieldError("password_check", result);
	}

	return result;
}

/* ************************************************************************ *
 *                     DO NOT EDIT FROM HERE ON                             *
 * ************************************************************************ */

yawaf.is = new Object();
yawaf.is.dom = true;

/* ************************************************************************ *
 *                          Rudimentary Logging                             *
 * ************************************************************************ */
yawaf.Log = function() {
	this.messages = "";
	this.isDebugEnabled = false;
	this.isInfoEnabled = false;
	this.isWarnEnabled = true;
	this.isErrorEnabled = true;
	this.isFatalEnabled = true;
}
yawaf.Log.prototype = new Object();

yawaf.Log.prototype.debug = function(message) {
	this.messages += "DEBUG: " + message + "\n";
}
yawaf.log = new yawaf.Log();

/* ************************************************************************ *
 *                  Java counterpart of MessageFormat                       *
 * ************************************************************************ */
/*
 * We want to have all messages that could be localized held in one file.
 * Since we must have properties file for java part or the framework, we
 * will specify messages that are common to java/javascript there and then
 * transfer some of the messages needed for javascript here, but we have
 * to implement MessageFormat.format() in javascript in order to have
 * messages stored in the same format in properties file.
 *
 * Format message with specified arguments.
 *
 * Inside the message single quotes are removed, use two quotes
 * to get single quote in the output.
 *
 * Only simple {argument index} are allowed (no subformats).
 *
 * @param message Message to be formatted.
 * @param field yawaf_data_Field object.
 */
yawaf.formatMessage = function(message) {
	var result = "";
	var i, n, ch, prev = ' ';
	var inArg = false;

	if (!message) {
		return "";
	}

	for (i = 0; i < message.length; i++) {
		ch = message.charAt(i);
		if (ch == '\'') {
			if (prev == '\'') {
				result += ch;
			}
		} else if (ch == '{') {
			inArg = true;
			n = 0;
		} else if (ch == '}') {
			var p = arguments[n + 1];
			if (n == 0 && yawaf.messages.fields[p]) {
				result += yawaf.messages.fields[p];
			} else {
				result += arguments[n + 1];
			}
			inArg = false;
		} else {
			if (inArg) {
				if (ch >= '0' && ch <= '9') {
					n = n * 10 + (ch - '0');
				} else {
					// Ignoring non digits inside the argument.
				}
			} else {
				result += ch;
			}
		}
		prev = ch;
	}
	return result;
}

/* ************************************************************************ *
 *                                  Form                                    *
 * ************************************************************************ */
/*
 * Return value of the field. It should be used only when you are certain that
 * field can have exactly one value.
 *
 * @param field field control name
 * @return Value of the field.
 */
yawaf.getFieldValue = function(form, field) {
	if (yawaf.log.isDebugEnabled) {
		yawaf.log.debug("Getting field " + field);
	}
	var length = form[field].length;
	var value;
		
	if (length) {
		for (var i = 0; i < form[field].length; i++) {
			var ctl = form[field][i];
			if (ctl.checked || ctl.selected) {
				value = form[field][i].value;
				break;
			}
		}
	} else {
		value = form[field].value;
	}
	return value;
}

/*
 * Return values of the field.
 *
 * @param field field control name
 * @return Array with the selected values of the field.
 */
yawaf.getFieldValues = function(form, field) {
	var length = form[field].length;
	var values = new Array();
		
	if (length) {
		for (var i = 0; i < form[field].length; i++) {
			var ctl = form[field][i];
			if (ctl.checked || ctl.selected) {
				values.push(form[field][i].value);
			}
		}
	} else {
		values.push(form[field].value);
	}
	return values;
}

/* ************************************************************************ *
 *                       Javascript data definition                         *
 * ************************************************************************ */
/*
 * FieldSet is used for both records and forms.
 */
yawaf.FieldSet = function(name) {
	this.name = name;
	this.fields = new Object();
	this.validators = new Array();
	this.errors = new Object();
	this.valid = false;
}
yawaf.FieldSet.prototype = new Object();

yawaf.FieldSet.prototype.isValid = function() {
	return this.valid;
}

yawaf.FieldSet.prototype.addField = function(fieldName, field) {
	var newField = new yawaf.Field(fieldName);
	
	if (field) {
		for (var i = 0; i < field.validators.length; i++) {
			var old = field.validators[i];
			var validator = new yawaf.FieldValidator(
				old.fn,
				old.args);
			validator.args = new Array();
			validator.args.push(fieldName);
			for (var j = 1; j < old.args.length; j++) {
				validator.args.push(old.args[j]);
			}
			newField.validators.push(validator);
		}
	}

	this.fields[fieldName] = newField;

	return newField;
}

yawaf.FieldSet.prototype.getValue = function(fieldName) {
	var value;
	
	if (this.fields[fieldName]) {
		value = this.fields[fieldName].value;
	}
	
	return value;
}

yawaf.FieldSet.prototype.addValidator = function(fn) {
	var args = new Array(this);
	// arguments is not an array!
	for (var i = 1; i < arguments.length; i++) {
		args.push(arguments[i]);
	}
	this.validators.push(new yawaf.FieldSetValidator(fn, args));
}

yawaf.FieldSet.prototype.setFieldError = function(fieldName, error) {
	var field = this.fields[fieldName];
	if (!field) return;
	
	this.valid = false;
	field.valid = false;
	field.errors.push(error);
	this.errors[fieldName] = field;
}

yawaf.FieldSet.prototype.setValues = function(formName) {
	var form;

	if (formName) {
		form = document.forms[formName];
	} else {
		form = document.forms[0];
	}

	for (var fieldName in this.fields) {
		var field = this.fields[fieldName];

		if (field.list) {
			field.value = yawaf.getFieldValues(form, fieldName);
		} else {
			field.value = yawaf.getFieldValue(form, fieldName);
		}
	}
	this.validate();
}

yawaf.FieldSet.prototype.validate = function() {
	this.errors = new Object();
	this.valid = true;

	for (var fieldName in this.fields) {
		var field = this.fields[fieldName];

		if (!field.validate(field.value)) {
			this.errors[fieldName] = field;
			this.valid = false;
		}
	}
	
	for (var i = 0; i < this.validators.length; i++) {
		var validator = this.validators[i];
		validator.validate(this);
	}
}

/*
 * FieldSets
 */
yawaf.FieldSets = function() {
}
yawaf.FieldSets.prototype = new Object();
yawaf.FieldSets.prototype.addFieldSet = function(name) {
	this[name] = new yawaf.FieldSet(name);
}

yawaf.records = new yawaf.FieldSets();
yawaf.forms = new yawaf.FieldSets();

/*
 * Field
 */
yawaf.Field = function(name) {
	this.name = name;
	this.validators = new Array();
	this.list = false;
	this.defaultValue = "";
	this.valid = false;
	this.errors = new Array();
}
yawaf.Field.prototype = new Object();

yawaf.Field.prototype.addValidator = function(fn) {
	var args = new Array(this.name, this.value);
	// arguments is not an array!
	for (var i = 1; i < arguments.length; i++) {
		args.push(arguments[i]);
	}
	this.validators.push(new yawaf.FieldValidator(fn, args));
}

yawaf.Field.prototype.validate = function(value) {
	var error;

	this.valid = true;
	this.errors = new Array();
	
	for (var i = 0; i < this.validators.length; i++) {
		error = this.validators[i].validate(value);
		if (error) {
			this.valid = false;
			this.errors.push(error);
		}
	}

	return this.valid;
}
	
yawaf.Field.prototype.toString = function() {
	return "Field " + this.name + " with value '" + this.value + "'"; 
}

/*
 * FieldValidator
 */
yawaf.FieldValidator = function(fn, args) {
	this.fn = fn;
	this.args = args;
}
yawaf.FieldValidator.prototype = new Object();

yawaf.FieldValidator.prototype.validate = function(value) {
	this.args[1] = value;
	return this.fn.apply(yawaf.validators, this.args);
}


/*
 * FieldSetValidator
 */
yawaf.FieldSetValidator = function(fn, args) {
	this.fn = fn;
	this.args = args;
}
yawaf.FieldSetValidator.prototype.validate = function(form) {
	this.args[0] = form;
	return this.fn.apply(yawaf.validators, this.args);
}


/*
 * Default form validation function.
 */
yawaf.oldStyles = new Object();
yawaf.skipValidaton = true;

function validateForm(formName) {
	var label;
	var errors = "";
	var form;
	
	if (yawaf.skipValidation) {
		return true;
	}
	
	yawaf.form = yawaf.forms[formName];
	yawaf.form.setValues(formName);

	for (fieldName in yawaf.form.fields) {
		if (yawaf.is.dom) {
			label = document.getElementById(fieldName + "_label");
		}
		if (!label) {
			continue;
		}
		if (yawaf.form.errors[fieldName]) {
			if (!yawaf.oldStyles[fieldName]) {
				yawaf.oldStyles[fieldName] = new Object();
				yawaf.oldStyles[fieldName].color = label.style.color;
				yawaf.oldStyles[fieldName].fontWeight = label.style.fontWeight;
				label.style.color = "red";
				label.style.fontWeight = "bold";
			}
			errors += yawaf.form.errors[fieldName].errors.join('\n') + "\n";
		} else {
			if (yawaf.oldStyles[fieldName]) {
				label.style.color = yawaf.oldStyles[fieldName].color;
				label.style.fontWeight = yawaf.oldStyles[fieldName].fontWeight;
				yawaf.oldStyles[fieldName] = undefined;
			}
		}
	}

	if (errors != "") {
		alert(errors);
		return false;
	}

	return yawaf.form.isValid();
}

function showErrors(fieldName) {
	var field;

	if (yawaf.form) {
		field = yawaf.form.errors[fieldName];
	}

	if (field) {
		alert(field.errors.join('\n'));
	}
}

