var AjaxValidation =
{
	map: new Array()
}

AjaxValidation.register = function(field, url, options)
{
	if(!options)
		options = {};
	
	AjaxValidation.map.push(new Array(field, url, options));
	AjaxValidation.prepare($(field));
}

AjaxValidation.getUrlForField = function(field)
{
	for(var i = 0; i < this.map.length; i++)
	{
		if(this.map[i][0] == field)
		{
			return this.map[i][1];
		}
	}
}

AjaxValidation.getOptionsForField = function(field)
{
	for(var i = 0; i < this.map.length; i++)
	{
		if(this.map[i][0] == field)
		{
			return this.map[i][2];
		}
	}
}

AjaxValidation.postBody = function(field)
{
	var post = field.getAttribute('name') + '=' + field.value;
	
	var options = AjaxValidation.getOptionsForField(field.getAttribute('id'));
	
	if(options.parameters)
	{
		post += '&' + options.parameters;
	}
	
	if(options.fields)
	{
		for(var i = 0; i < options.fields.length; i++)
		{
			var additionalField = $(options.fields[i]);
			
			if(additionalField)
			{
				post += '&' + additionalField.getAttribute('name') + '=' + additionalField.value;
			}
		}
	}
	
	return encodeURI(post);
}

AjaxValidation.prepare = function(field)
{
	var options = AjaxValidation.getOptionsForField(field.getAttribute('id'));
	
	if(typeof options.setResult != 'undefined')
	{
		if(!$(AjaxValidation.getContainerName(field)))
		{
			AjaxValidation.createContainer(field);
		}
		
		$(AjaxValidation.getContainerName(field)).className = !options.setResult ? 'ajaxValidationError' : 'ajaxValidationOk';
	}
	
	if(!$(AjaxValidation.getContainerName(field)))
	{
		var container = AjaxValidation.createContainer(field);
		container.className = 'ajaxValidationNone';
	}
	
	var onFunctions = Array('blur');
	
	var fieldType = field.getAttribute('type');
	if(fieldType) fieldType = fieldType.toLowerCase();
	
	if(fieldType == 'radio' || fieldType == 'checkbox')
	{
		onFunctions.push('click');
	}
	
	if(field.nodeName.toLowerCase() == 'select')
	{
		onFunctions.push('change');
	}
	
	for(var i = 0; i < onFunctions.length; i++)
	{
		Event.observe(field, onFunctions[i], function()
		{
			AjaxValidation.validate(field);
		});
	}
}

AjaxValidation.validate = function(field)
{
	var options = AjaxValidation.getOptionsForField(field.getAttribute('id'));
	
	if(typeof options.processor == 'function')
	{
		options.processor(field);
	}
	else // default ajax processor
	{
		var request =
		{
			method: 'post',
			postBody: AjaxValidation.postBody(field),
			
			onSuccess: function(XMLHttpRequest)
			{
				AjaxValidation.processResponse(field, XMLHttpRequest.responseText);
			}
		};
		
		new Ajax.Request(AjaxValidation.getUrlForField(field.getAttribute('id')), request);
		$(AjaxValidation.getContainerName(field)).className = 'ajaxValidationLoader';
	}
}

AjaxValidation.processResponse = function(field, response)
{
	var error = response == 1 ? false : true;
	
	$(AjaxValidation.getContainerName(field)).className = error ? 'ajaxValidationError' : 'ajaxValidationOk'
	
	if(!error)
	{
		// hide error message
		if($(AjaxValidation.getErrorContainerName(field)))
		{
			AjaxValidation.deleteErrorMessageContainer(field);
		}
	}
	
	response = new String(response);
	
	if(error && response.indexOf('|') > 0)
	{
		var response = response.split('|');
		var errorMessage = response[1];
		
		var errorContainer = $(AjaxValidation.getErrorContainerName(field));
		if(errorContainer)
			errorContainer.innerHTML = errorMessage;
	}
}

AjaxValidation.getContainerName = function(field)
{
	var options = AjaxValidation.getOptionsForField(field.getAttribute('id'));
	
	if(options.container)
		return options.container;
	else
		return field.getAttribute('id') + 'AjaxValidation';
}

AjaxValidation.getErrorContainerName = function(field)
{
	var options = AjaxValidation.getOptionsForField(field.getAttribute('id'));
	
	if(options.container)
		return options.container + 'AVEM';
	else
		return field.getAttribute('id') + 'AVEM';
}

AjaxValidation.createContainer = function(field)
{
	var containerName = AjaxValidation.getContainerName(field);
	
	var container = document.createElement('div');
	container.innerHTML = "&nbsp;";
	container.id = containerName;
	
	field.parentNode.insertBefore(container, field.nextSibling);
	
	return container;
}

AjaxValidation.insertContainer = function(field, error)
{
	document.write('<div id="' + field + 'AjaxValidation" class="' + (error ? 'ajaxValidationError' : 'ajaxValidationOk') + '"></div>');
}

AjaxValidation.deleteErrorMessageContainer = function(field)
{
	var container = $(AjaxValidation.getErrorContainerName(field));
	
	if(container)
	{
		var options = AjaxValidation.getOptionsForField(field.getAttribute('id'));
	
		var behavior = 'empty';
		
		if(options.errorMessageBehavior)
		{
			behavior = options.errorMessageBehavior;
		}
		
		switch(behavior)
		{
			case 'empty':
				if(container.innerHTML.length > 0) container.innerHTML = '';
				break;
			case 'remove': container.remove(); break;
			default: container.empty();
		}
	}
}

