/* 
 * Create global 'sdg' object - this is the only global object we create.
 * All other functions and objects should be apart of this.
 */

if (!window.sdg) {
	sdg = {};
}

var currentStage = '';

/*
 * Applies a class of 'err' to the labels of form fields with errors (they turn
 * red with a !)
 *  - jsonObject: the JSON object returned by the server side script - formId:
 * the unique id of the form
 */

sdg.labelErrors = function(jsonObject, formId) {

	if (jsonObject.inputErrors != undefined
			&& jsonObject.inputErrors.length > 0) {
		var inputErrors = jsonObject.inputErrors;

		formId = (formId != undefined) ? formId : '';
		$sd('label,div.label').removeClass('err');

		for ( var i in inputErrors) {
			fieldName = inputErrors[i]['name']
			splitResult = fieldName.split(",");
			for ( var j = 0; j < splitResult.length; j++) {
				idx = splitResult[j].indexOf(".");
				fieldName = splitResult[j].substr(++idx);
				fieldName = fieldName.substr(0, 1).toUpperCase()
						+ fieldName.substr(1);
				fieldId = 'frm' + fieldName;
				errorMsg = inputErrors[i]['description'];
				if ($sd('label[for="' + fieldId + '"]').length > 0)
					$sd('label[for="' + fieldId + '"]').addClass('err');
				else
					$sd('#lbl' + formId + fieldName).addClass('err');
			}
		}
	}
}

/*
 * Generic error display method Generates a list of error messages
 *  - jsonObject: the JSON object returned by the server side script -
 * errorLocation: the containing element for the error message
 */

sdg.listErrors = function(jsonObject, errorLocation) {

	if (jsonObject.inputErrors != undefined
			&& jsonObject.inputErrors.length > 0) {
		var inputErrors = jsonObject.inputErrors;

		$sd('ul.err').remove();
		errorOutput = '<ul class="err">';
		for ( var i in inputErrors) {
			errorMsg = inputErrors[i]['description'];
			errorOutput += '<li>' + errorMsg + '</li>';
		}
		errorOutput += '</ul>';
		$sd(errorLocation).prepend(errorOutput);
	}
}

/*
 * Submit an ATG form via ajax - expects a JSON response object params should
 * contain the following members:
 *  - trigger: the element that triggered the submission, usually a submit
 * button - error: a callback function triggered on an error response from the
 * ajax call - success: a callback function triggered on a successful response
 * from the ajax call
 */

sdg.submitAjaxForm = function(params) {

	/*
	 * Get the form that this element is a part of.
	 */
	var trigger = (params.trigger.attr('action') == undefined ? params.trigger : $sd('#'+params.trigger.attr('id') + ' .submitBtn'));             
	var formNode = trigger.parents("form").get(0);
	var url = formNode.action;
	
	var data = sdg.extractFormData(trigger, params.jsonDataToSubmit);
	var dataType = params.dataType ? params.dataType : 'html';
	
	/*
	 * Prevent the user from submitting the form twice.
	 */

	if (trigger.data("justClicked")) {
		return false;
	} else {
		trigger.data("justClicked", true);
	}

	/*
	 * If a disabledValue has been specified, replace the submit button (link)
	 * with the new content.
	 */

	if (trigger.attr("disabledValue")) {
		var linkNode = trigger.data("replacedByLink");

		linkNode.data("originalContent", linkNode.html());
		linkNode.html("<span>" + trigger.attr("disabledValue") + "</span>");
		linkNode.addClass("disabledValueContent");
	}

	/*
	 * POST the form using jQuery's standard ajax functionality.
	 */

	$sd.ajax( {
		cache :false,
		data :data,
		dataType :dataType,
		error :params.error,
		success :params.success,
		async :false,
		complete : function() {

			/*
			 * If we disabled any buttons then we need to enable them.
			 */

			trigger.data("justClicked", false);

			var linkNode = trigger.data("replacedByLink");

			if (linkNode && linkNode.data("originalContent")) {
				linkNode.html(linkNode.data("originalContent"));
			}
		},
		type :"POST",
		url :url
	});
};

/*
 * Extract all name/value pairs from a form and return as a data object ready to
 * pass in an XHR call Takes the trigger node as param (the button clicked to
 * trigger the form submission)
 */

sdg.extractFormData = function(trigger, jsonDataToSubmit) {

	var triggerNode = trigger.get(0);
	var formNode = trigger.parents("form").get(0);
	
	/*
	 * Build all form fields into a data object excluding submit buttons for now -
	 * we only want the one that was actually clicked to trigger the form
	 * submission.
	 */

	var data = {};
	
	if(jsonDataToSubmit != undefined){
		data["jsonDataToSubmit"] = JSON.stringify(jsonDataToSubmit);
	}
	
	$sd(':input[type!=submit][type!=image]', formNode)
			.each(
					function() {

						/*
						 * Exclude fields with no name and unchecked checkboxes.
						 */

						if (this.name !== ''
								&& !((this.type === 'checkbox' || this.type === 'radio') && this.checked === false)) {
							data[this.name] = this.value;
						}
					});

	/*
	 * Add back in the name/value pair of the submit button that was actually
	 * clicked - FormHandler machinery needs this to invoke the correct
	 * handleXxx method. For image buttons it also needs to see the X/Y
	 * coordinates that the browser submits so we simulate these.
	 */

	if ((triggerNode.type === "submit" || triggerNode.type === "image")
			&& triggerNode.name !== "") {
		if (triggerNode.type === "image") {
			data[triggerNode.name + '.x'] = 0;
			data[triggerNode.name + '.y'] = 0;
		}
		data[triggerNode.name] = triggerNode.value;
	}

	return data;
}

/*
 * If there's an error then we redirect to the URL that should always be passed
 * to us by the server.
 */

sdg.checkForResponseError = function(responseData) {
	if (responseData.error) {
		document.location.href = responseData.redirectUrl;
	}
}

/*
 * Dynamically include a Javascript file
 */
sdg.includeDom = function(script_filename) {
	var html_doc = document.getElementsByTagName('head').item(0);
	var js = document.createElement('script');
	js.setAttribute('language', 'javascript');
	js.setAttribute('type', 'text/javascript');
	js.setAttribute('src', script_filename);
	html_doc.appendChild(js);
	return false;
}

/*
 * Get any variables passed in the Querystring
 */
var qsParm = new Array();
sdg.qs = function() {
	var query = window.location.search.substring(1);
	var parms = query.split('&');
	for ( var i = 0; i < parms.length; i++) {
		var pos = parms[i].indexOf('=');
		if (pos > 0) {
			var key = parms[i].substring(0, pos);
			var val = parms[i].substring(pos + 1);
			qsParm[key] = val;
		}
	}

	return qsParm;
}

/*
 * Ajax form submit wrapper
 */
sdg.submitChange = function(trigger, successfunction, noProcessing, jsonDataToSubmit) {
	if (($sd("#TB_window").length < 1) && !noProcessing)
		sdg.process('start');
	sdg.submitAjaxForm( {
		trigger :trigger,
		jsonDataToSubmit : jsonDataToSubmit,
		dataType :'json',
		error : function(request, status, error) {
			alert("error:" + error + " status:" + status);
			if(!noProcessing)
				sdg.process('end');
		},
		success : function(data, textStatus) {
			if(!noProcessing) {
				sdg.process('end', function() {
					sdg.checkForResponseError(data);
					successfunction(data);
				});
			} else {
				sdg.checkForResponseError(data);
				successfunction(data);
			}
		}
	});
};

/*
 * Retrieves file contents (either HTML or JSON) via an Ajax request
 * 
 * Function properties - targetDiv: Div you wish to insert contents in to - url:
 * Url of the JSON or HTML file to be requested by AJAX - format: JSON or HTML -
 * specificFunction: (optional) A custom function to call - errorFunction:
 * (optional) A custom error function passed to loadStage
 */
sdg.ajaxRetrieve = function(targetDiv, url, format, defaultStage,
		formNameParam, specificFunction, errorFunction) {
	format = format.toLowerCase();
	formNameParam = (formNameParam) ? formNameParam : '';	
	$sd.ajax( {
		url :url,
		cache :false,
		datatype :format,
		success : function(data) {
			
			if (format == 'json') {
				eval('var data = ' + data);
			}
			if ((data.stage == undefined || data.stage.length < 1)
					&& !formNameParam) {
				formName = '#' + data.stage + 'Form';
			} else {
				formName = (formNameParam) ? formNameParam
						: '#' + data.stage + 'Form';
			}

			$sd(formName + ' ul.err').remove();
			contents = (format == 'json') ? data.stepContents : data;

			$sd(targetDiv + ' .formBox').html(contents).slideDown(
					'normal',
					function() {
						sdg.assignEventHandlers(data, formName, formNameParam,
								specificFunction, errorFunction);
					});

			currentStage = (format == 'json') ? data.stage : defaultStage;
			
		}
	});
}

/*
 * Assign event handlers to the form
 * 
 * Function parameters - data: JSON object - formName: Target div -
 * formNameParam: If specified this overrides the stage attribute returned by
 * the JSON - specificFunction: (optional) A custom function to call -
 * errorFunction: (optional) A custom error function that overrides the standard
 * error functionality
 */
sdg.assignEventHandlers = function(data, formName, formNameParam,
		specificFunction, errorFunction, noProcessing) {
	 
	if (specificFunction) {
		var isFunc = $sd.isFunction(specificFunction);
		
		if (isFunc) {
			specificFunction(data);
		} else {
			eval('sdg.' + specificFunction + ';');
		}
	}
	
	$sd(formName + ' .submitBtn').live(
				'click',
				function(event) {
					sdg.loadStage(this, formNameParam, specificFunction,
							errorFunction, noProcessing);
					return false;							
				});
	
	$sd(formName + ' form').submit(function(event) {
		event.preventDefault();
		sdg.loadStage(this, formNameParam, specificFunction, errorFunction, noProcessing);
		return false;
	});
	
}

/*
 * Load a particular stage and handle any validation errors
 * 
 * Function parameters - btn: Submit button object - formNameParam: If specified
 * this overrides the stage attribute returned by the JSON - specificFunction:
 * (optional) A custom function to call - errorFunction: (optional) A custom
 * error function that overrides the standard error functionality - noSlide:
 * (optional) If true the accordion effect is not used
 * 
 * Properties used from the returned JSON object - stage: section name
 * identifier (e.g personalDetails). A div of the same name (+Form) will be
 * present in registration.jsp - inputErrors: An array containing any form
 * validation errors - stepContents: A property containing the html that will be
 * return by Ajax.
 * 
 * Json properties for confirmation dialog prompts - confirmDialog: function to
 * call - popupUrl: Url of the page to load in the dialog
 */
sdg.loadStage = function(btn, formNameParam, specificFunction, errorFunction,
		noSlide, noProcessing, jsonDataToSubmit) {
	
	sdg.submitChange($sd(btn), function(data) {
		
		if ((data.stage == undefined || data.stage.length < 1)
				&& !formNameParam) {
			formName = '#' + currentStage + 'Form';
		} else {
			formName = (formNameParam) ? formNameParam
					: '#' + data.stage + 'Form';
		}
		if (data.inputErrors != undefined && data.inputErrors.length > 0) {
			var standardErrorBehaviour = true;

			if (errorFunction) {
				standardErrorBehaviour = errorFunction(data);
			}

			if (standardErrorBehaviour) {
				sdg.labelErrors(data);
				sdg.listErrors(data, formName + ' .formBox');
			}
		} else {
			$sd(formName + ' ul.err').remove();
			if (!formNameParam && !noSlide) {
				$sd('.formBox:visible').slideUp(
						'normal',
						function() {
							$sd(this).empty();
							$sd(formName + ' .formBox').html(data.stepContents)
									.slideDown(
											'normal',
											function() {
												sdg.assignEventHandlers(data,
														formName,
														formNameParam,
														specificFunction,
														errorFunction, noProcessing);
											});
						});
			} else if (formNameParam || noSlide) {
				$sd(formName + ' .formBox').html(data.stepContents).slideDown(
						'normal');
							sdg.assignEventHandlers(data, formName,
									formNameParam, specificFunction,
									errorFunction, noProcessing);
						
			}
			currentStage = data.stage;
		}
	}, noProcessing, jsonDataToSubmit);
}

/*
 * Display confirmation dialog box
 */
sdg.confirmDialog = function(data, callback) {

	$sd('.actions .close').live('click', function() {
		if (callback) {
			eval('sdg.' + callback + '("close");');
		}
		tb_remove();
		return false;
	});

	$sd('.actions .resume').live('click', function() {
		if (callback) {
			eval('sdg.' + callback + '("resume");');
		}
		tb_remove();
		return false;
	});

	// THIS TEMPORARILY GETS AROUND A PROBLEM OF POPPING
	// UP THE CONFIRM DIALOG WHILE THE PROCESSING MESSAGE
	// HASN'T YET DISAPPEARED

	setTimeout( function() {
		tb_show('Confirm', data.popupUrl + '?width=500&height=250', null);
	}, 4000);
}