/*	Turns the provided form and registration elements into an interactive registration dialogue. Auotmatically
	highlights instructions as the user tabs through the registration dialogue and performs client-side error checking.
	Responds to server side errors as well by checking 'error_code' in query string.
	
	sFormID: The id of the form in question
	aRegistrationElements: An array of registration elements
*/
function Registration(sFormId, aRegistrationElements)
{
	var oThis = this;
	
	this.form = document.getElementById(sFormId);
	this.elements = aRegistrationElements;
}

Registration.prototype.validate = function()
{
	for (var i = 0; i < this.elements.length; i ++)
		if (!this.elements[i].validate())
			return false;
	
	return true;
};

/*	sElementId: The form element in question
	sInstructionId: What instructions should be highlighted when sElementId has focus. (Also where error messages are shown)
	oClientConditions: A single ClientCondition or an array of ClientCconditions that must be satisfied before this element
					   is ok for submission
	oServerConditions: A single ServerCondition or an array of ServerConditions that will be returned if if this element isn't
					   successfully validated server side.
	aCss: The css classes to apply. Options are 'Instruction', 'ErrorMessage', and 'SelectedInstruction'.
*/
function RegistrationElement(sElementId, sInstructionId, oClientConditions, oServerConditions, aCss)
{
	this.element = document.getElementById(sElementId);
	this.instruction = document.getElementById(sInstructionId);
	this.instruction_text = this.instruction.innerHTML;
	
	// If oClientConditions or oServerConditions are passed as a single object instead of an array, convert them to an array
	this.client_conditions = (oClientConditions && oClientConditions.length === undefined) ? new Array(oClientConditions) : oClientConditions;
	this.server_conditions = (oServerConditions && oServerConditions.length === undefined) ? new Array(oServerConditions) : oServerConditions;
	
	if (!this.client_conditions) this.client_conditions = new Array();
	if (!this.server_conditions) this.server_conditions = new Array();
	
	this.css = aCss;
	this.error = false;		// When an error occurs for this field, this is set to true.
	
	this.init();
}

RegistrationElement.prototype.init = function()
{
	this.instruction.className = this.css.Instruction;
	
	var oThis = this;
	
	Util.AddEvent(this.element, 'focus',
		function() {
			if (!oThis.error)
				oThis.instruction.className = (oThis.css.Instruction + ' ' + oThis.css.SelectedInstruction);
		}
	);
	
	Util.AddEvent(this.element, 'blur', function() { oThis.validate() });
	
	// Re-validate while the user updates the state of the element
	if (this.element.getAttribute('type') == 'text' || this.element.getAttribute('type') == 'password')
		Util.AddEvent(this.element, 'keyup', function() { if (oThis.error) oThis.validate() });
	else
		Util.AddEvent(this.element, 'click', function() { if (oThis.error) oThis.validate() });
	
	var error_code = Util.QueryString('error_code');
	
	if (error_code)		// Show error messages from server side validation, if necessary
	{
		for (var j = 0; j < this.client_conditions.length; j ++)
		{
			if (error_code == this.client_conditions[j].sErrorCode) {
				this.instruction.innerHTML = this.client_conditions[j].sErrorMessage;
				this.instruction.className = this.css.ErrorMessage;
				this.error = true;
				break;
			}
		}
		
		if (this.error) return;		// Already found an error
		
		for (var j = 0; j < this.server_conditions.length; j ++)
		{
			if (error_code == this.server_conditions[j].sErrorCode)
			{
				this.error = true;
				this.instruction.innerHTML = this.server_conditions[j].sErrorMessage;
				this.instruction.className = this.css.ErrorMessage;
				break;
			}
		}
	}
};

RegistrationElement.prototype.validate = function()
{
	this.instruction.innerHTML = this.instruction_text;
	this.instruction.className = this.css.Instruction;
	this.error = false;
	
	for (var i = 0; i < this.client_conditions.length; i ++)
		if (!this.client_conditions[i].fCondition(this.element))
		{
			this.error = true;
			this.instruction.innerHTML = this.client_conditions[i].sErrorMessage;
			this.instruction.className = this.css.ErrorMessage;
			return false;
		}
		
	return true;
};

/*	fCondition: Returns true if the condition is satisfied, false otherwise
	sErrorMessage:	The message shown if the condition isn't satisfied
*/
function ClientCondition(fCondition, sErrorMessage, sErrorCode)
{
	this.fCondition = fCondition;
	this.sErrorMessage = sErrorMessage;
	this.sErrorCode = sErrorCode;
}

/*	sErrorCode: The error code returned if a form element isn't successfully validated server side
	sErrorMessage: The error message to be shown
*/
function ServerCondition(sErrorCode, sErrorMessage)
{
	this.sErrorCode = sErrorCode;
	this.sErrorMessage = sErrorMessage;
}