/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                 //
//                                         ___           ___                                                       //
//                                        /__/\         /  /\         _____                                        //
//                                       _\_ \:\       /  /:/_       /  /::\                                       //
//                                      /__/\ \:\     /  /:/ /\     /  /:/\:\                                      //
//                                     _\_ \:\ \:\   /  /:/ /:/_   /  /:/~/::\                                     //
//                                    /__/\ \:\ \:\ /__/:/ /:/ /\ /__/:/ /:/\:|                                    //
//                                    \  \:\ \:\/:/ \  \:\/:/ /:/ \  \:\/:/~/:/                                    //
//                                     \  \:\ \::/   \  \::/ /:/   \  \::/ /:/                                     //
//                                      \  \:\/:/     \  \:\/:/     \  \:\/:/                                      //
//                                       \  \::/       \  \::/       \  \::/                                       //
//                                        \__\/         \__\/         \__\/                                        //
//        ___           ___                         ___                                   ___           ___        //
//       /  /\         /  /\                       /__/\          ___       ___          /  /\         /__/\       //
//      /  /:/_       /  /::\                      \  \:\        /  /\     /  /\        /  /::\        \  \:\      //
//     /  /:/ /\     /  /:/\:\    ___     ___       \  \:\      /  /:/    /  /:/       /  /:/\:\        \  \:\     //
//    /  /:/ /::\   /  /:/  \:\  /__/\   /  /\  ___  \  \:\    /  /:/    /__/::\      /  /:/  \:\   _____\__\:\    //
//   /__/:/ /:/\:\ /__/:/ \__\:\ \  \:\ /  /:/ /__/\  \__\:\  /  /::\    \__\/\:\__  /__/:/ \__\:\ /__/::::::::\   //
//   \  \:\/:/~/:/ \  \:\ /  /:/  \  \:\  /:/  \  \:\ /  /:/ /__/:/\:\      \  \:\/\ \  \:\ /  /:/ \  \:\~~\~~\/   //
//    \  \::/ /:/   \  \:\  /:/    \  \:\/:/    \  \:\  /:/  \__\/  \:\      \__\::/  \  \:\  /:/   \  \:\  ~~~    //
//     \__\/ /:/     \  \:\/:/      \  \::/      \  \:\/:/        \  \:\     /__/:/    \  \:\/:/     \  \:\        //
//       /__/:/       \  \::/        \__\/        \  \::/          \__\/     \__\/      \  \::/       \  \:\       //
//       \__\/         \__\/                       \__\/                                 \__\/         \__\/       //
//                           ___           ___           ___           ___           ___                           //
//                          /  /\         /__/\         /  /\         /  /\         /__/|                          //
//                         /  /:/_        \  \:\       /  /::\       /  /:/        |  |:|                          //
//                        /  /:/ /\        \__\:\     /  /:/\:\     /  /:/         |  |:|                          //
//                       /  /:/ /::\   ___ /  /::\   /  /:/~/::\   /  /:/  ___   __|  |:|                          //
//                      /__/:/ /:/\:\ /__/\  /:/\:\ /__/:/ /:/\:\ /__/:/  /  /\ /__/\_|:|____                      //
//                      \  \:\/:/~/:/ \  \:\/:/__\/ \  \:\/:/__\/ \  \:\ /  /:/ \  \:\/:::::/                      //
//                       \  \::/ /:/   \  \::/       \  \::/       \  \:\  /:/   \  \::/~~~~                       //
//                        \__\/ /:/     \  \:\        \  \:\        \  \:\/:/     \  \:\                           //
//                          /__/:/       \  \:\        \  \:\        \  \::/       \  \:\                          //
//                          \__\/         \__\/         \__\/         \__\/         \__\/                          //
//                                                                                                                 //
//                                                                                                                 //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                 //
//                                       W e b   S o l u t i o n   S h a c k                                       //
//                                                    Matt Rabe                                                    //
//                                                       '10                                                       //
//                                                                                                                 //
//                                             www.websolutionshack.com                                            //
//                                                                                                                 //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
// Initial Setup
////////////////////////////////////////////////////////////////////////////////////

var AjaxTransfer = Class.create({
	initialize: function(varname)
	{
		///////////////////////////////////////////////////////////////////////////////////////////
		// START CONFIGURATION //
	
		this.transferprocessor = '/ajaxtransfers/ajaxtransfer.php';	// Set this to the location of the PHP file that processes AJAX Tranfers

		this.defaultShowErrors = true;					// Automatically display error responses?
		this.defaultShowSuccesses = true;				// Automatically display success responses?
	
		// END CONFIGURATION //
		///////////////////////////////////////////////////////////////////////////////////////////
	
	
	
		this.self = (varname != null ? varname : 'ajax');

		this.wrapper_id = (this.wrapper_id != null ? this.wrapper_id : 'ajax_responses_wrapper');
		this.error_id = (this.error_id != null ? this.error_id : 'ajax_responses_error');
		this.success_id = (this.success_id != null ? this.success_id : 'ajax_responses_success');
		this.loading_id = (this.loading_id != null ? this.loading_id : 'ajax_responses_loading');
		this.text_id = (this.text_id != null ? this.text_id : 'ajax_responses_text');

		this.pendingTransfers = 0;
		this.error = false;
		this.success = false;
	},

	clean: function(str)
	{
		return core.clean(str);
	},
	
	cleanQuotes: function(str)
	{
		return core.cleanQuotes(str);
	},

	encode: function(str)
	{
		return encodeURI(escape(str.toString().replace(/%/g, 'wssatitagain'))).replace(/wssatitagain/g, '%25');
	},

	decode: function(str)
	{
		return decodeURI(str);
	},
	
	get: function(url, cb, params)	// responses.wrapperId is the default param.  If a string is sent for params, it will be used as params.responses.wrapperId
	{
		// Execute only if no other transfers are currently pending
		if (this.pendingTransfers == 0)
		{
			// Data protection and defaulting
			if (params == undefined) params = [];
			if (typeof(params) == 'string')
			{
				responsesId = params;

				params = [];
				params.responses = [];
				params.responses.wrapperId = responsesId;
			}
			if (!params.responses) params.responses = [];
			if (!params.responses.wrapperId) params.responses.wrapperId = '';
			params.responses.showErrors = (params.responses.showErrors != null ? params.responses.showErrors : this.defaultShowErrors);
			params.responses.showSuccesses = (params.responses.showSuccesses != null ? params.responses.showSuccesses : this.defaultSshowSuccesses);

			// Fire the call, with callback, ITIS
			if (typeof(cb) != 'function')
			{
				this._get(url, null, params);
			}else{
				this._get(url, (typeof(cb) == 'function' ? cb : null), params);
			}
		}
	},

	_get: function(url, cb, params)
	{
		// Initiate loading lock (can't start another load)
//		this.loading(params.responses.wrapperId);

		new Ajax.Request(url,
		{
			onSuccess: this.successHandler(this.self, cb, params),
			onFailure: this.failureHandler(this.self, cb, params),
			onTimeout: this.timeoutHandler(this.self, cb, params),
			onComplete: this.completeHandler(this.self, cb, params)
		});
	},
	
	transfer: function(url, cb, params)	// responses.wrapperId is the default param.  If a string is sent for params, it will be used as params.responses.wrapperId
	{
		// Execute only if no other transfers are currently pending
		if (this.pendingTransfers == 0)
		{
			// Data protection and defaulting
			if (typeof(params) == 'string')
			{
				responsesId = params;

				params = [];
				params.responses = [];
				params.responses.wrapperId = responsesId;
			}
			if (!params) params = [];
			if (!params.responses) params.responses = [];
			if (!params.responses.wrapperId) params.responses.wrapperId = '';
			params.responses.showErrors = (params.responses.showErrors != null ? params.responses.showErrors : this.defaultShowErrors);
			params.responses.showSuccesses = (params.responses.showSuccesses != null ? params.responses.showSuccesses : this.defaultSshowSuccesses);

			if (typeof(cb) != 'function')
			{
				this._transfer(url, null, params);
			}else{
				this._transfer(url, (typeof(cb) == 'function' ? cb : null), params);
			}
		}
	},

	_transfer: function(url, cb, params)
	{
		// Initiate loading lock (can't start another load)
		this.loading(params.responses.wrapperId);

		new Ajax.Request(this.transferprocessor,
		{
			parameters: url.replace(/&amp;/g, '&'),

			onSuccess: this.successHandler(this.self, cb, params),
			onFailure: this.failureHandler(this.self, cb, params),
			onTimeout: this.timeoutHandler(this.self, cb, params),
			onComplete: this.completeHandler(this.self, cb, params)
		});
	},

	loading: function(responsesId)
	{
		previouslyLoading = (this.pendingTransfers > 0 ? true : false);

		if (!previouslyLoading)
		{
			this.showLoadingIndicator(responsesId);
		}

		this.pendingTransfers++;
		
		return previouslyLoading;
	},
	
	done: function(responsesId)
	{
		if (this.pendingTransfers > 0)
		{
			this.pendingTransfers--;

			// Show Error icon, if there's an error
			if (this.error)
			{
				this.showError(responsesId);
			}else if (this.success)
			{
				this.showSuccess(responsesId);
			}else{
				// Hide loading indicator
				if (this.pendingTransfers == 0 && $(this.loading_id) || $$('#'+responsesId+' .ajax_responses_loading')[0])
				{
					this.hideLoadingIndicator(responsesId);
				}
			}		
		}else{
			return false;
		}
	},

	showLoadingIndicator: function(responsesId, cb)
	{
		// Data protection
		if (!$(responsesId)) return;
		cb = (typeof(cb) == 'function' ? cb : function() {});

		// Hide Error indicator, ITIS
		if ($$('#'+responsesId+' .ajax_responses_error')[0])
		{
			$$('#'+responsesId+' .ajax_responses_error')[0].hide();
		}else if ($(this.error_id))
		{
			$(this.error_id).hide();
		}

		// Hide Success indicator, ITIS
		if ($$('#'+responsesId+' .ajax_responses_success')[0])
		{
			$$('#'+responsesId+' .ajax_responses_success')[0].hide();
		}else if ($(this.success_id))
		{
			$(this.success_id).hide();
		}

		// Hide Response text, ITIS
		this.clearResponse(responsesId);

		// Show loading indicator
		if ($$('#'+responsesId+' .ajax_responses_loading')[0])
		{
			$$('#'+responsesId+' .ajax_responses_loading')[0].appear({duration: .2, afterFinish: cb});
		}else if ($(this.loading_id))
		{
			$(this.loading_id).appear({duration: .2, afterFinish: cb});
		}
	},

	hideLoadingIndicator: function(responsesId, cb)
	{
		// Data protection
		if (!$(responsesId)) return;
		cb = (typeof(cb) == 'function' ? cb : function() {});
		
		// Show loading indicator, ITIS
		if ($$('#'+responsesId+' .ajax_responses_loading')[0])
		{
			$$('#'+responsesId+' .ajax_responses_loading')[0].fade({from: 1, to: 0, duration: .2, afterFinish: cb});
		}else if ($(this.loading_id))
		{
			$(this.loading_id).fade({from: 1, to: 0, duration: .2, afterFinish: cb});
		}
	},
	
	addSuccess: function(success, responsesId)
	{
		// Data protection
		if (!$(responsesId)) return;

		if ($$('#'+responsesId+' .ajax_responses_text')[0])
		{
			$$('#'+responsesId+' .ajax_responses_text')[0].innerHTML = success;
		}else if ($(this.text_id))
		{
			$(this.text_id).innerHTML = success;
		}
		
		this.success = true;
	},
	
	showSuccess: function(responsesId)
	{
		// Data protection
		if (!$(responsesId)) return;

		if (this.success && ($(this.success_id) || $$('#'+responsesId+' .ajax_responses_success').first()))
		{
			// Hide loading indicator
			if ($$('#'+responsesId+' .ajax_responses_loading')[0])
			{
				$$('#'+responsesId+' .ajax_responses_loading')[0].hide();
			}else if ($(this.loading_id))
			{
				$(this.loading_id).hide();
			}

			// Show success icon
			if ($$('#'+responsesId+' .ajax_responses_success')[0])
			{
				// Set class name, ITIS
				if ($(responsesId).className.match(/ajax_responses_wrapper/))
				{
					$(responsesId).addClassName('successes');
					$(responsesId).removeClassName('infos');
					$(responsesId).removeClassName('notices');
					$(responsesId).removeClassName('errors');
				}

				$$('#'+responsesId+' .ajax_responses_success')[0].show();
			}else if ($(this.success_id))
			{
				$(this.success_id).show();
			}

			// Show text
			if ($$('#'+responsesId+' .ajax_responses_text')[0])
			{
				$$('#'+responsesId+' .ajax_responses_text')[0].show();
			}else if ($(this.text_id))
			{
				$(this.text_id).show();
			}

			// Fade out success message after X seconds
			if ($$('#'+responsesId+' .ajax_responses_success')[0])
			{
				$$('#'+responsesId+' .ajax_responses_success')[0].show();
				window.setTimeout('$$(\'#'+responsesId+' .ajax_responses_success\')[0].fade({from: 1, to: 0, duration: 1}); $$(\'#'+responsesId+' .ajax_responses_text\')[0].fade({from: 1, to: 0, duration: 1});', 5000)
			}else if ($(this.success_id))
			{
				window.setTimeout('$(\''+this.success_id+'\').fade({from: 1, to: 0, duration: 1}); $(\''+this.text_id+'\').fade({from: 1, to: 0, duration: 1});', 5000)
			}
		}
	},
	
	hideSuccess: function(responsesId)
	{
		// Data protection
		if (!$(responsesId)) return;

		// Hide success icon
		if ($$('#'+responsesId+' .ajax_responses_success')[0])
		{
			// Remove class name, ITIS
			if ($(responsesId).className.match(/ajax_responses_wrapper/))
			{
				$(responsesId).removeClassName('successes');
			}

			$$('#'+responsesId+' .ajax_responses_success')[0].hide();
		}else if ($(this.success_id))
		{
			$(this.success_id).hide();
		}
	},
	
	addError: function(error, responsesId)
	{
		// Data protection
		if (!$(responsesId)) return;

		if ($$('#'+responsesId+' .ajax_responses_text')[0])
		{
			$$('#'+responsesId+' .ajax_responses_text')[0].innerHTML = error;
		}else if ($(this.text_id))
		{
			$(this.text_id).innerHTML = error;
		}
		
		this.error = true;
	},
	
	showError: function(responsesId)
	{
		// Data protection
		if (!$(responsesId)) return;

		if (this.error)
		{
			// Hide loading indicator
			if ($$('#'+responsesId+' .ajax_responses_loading')[0])
			{
				$$('#'+responsesId+' .ajax_responses_loading')[0].hide();
			}else if ($(this.loading_id))
			{
				$(this.loading_id).hide();
			}

			// Show error icon
			if ($$('#'+responsesId+' .ajax_responses_error')[0])
			{
				// Set class name, ITIS
				if ($(responsesId).className.match(/ajax_responses_wrapper/))
				{
					$(responsesId).removeClassName('successes');
					$(responsesId).removeClassName('infos');
					$(responsesId).removeClassName('notices');
					$(responsesId).addClassName('errors');
				}

				$$('#'+responsesId+' .ajax_responses_error')[0].show();
			}else if ($(this.error_id))
			{
				$(this.error_id).show();
			}

			// Show text
			if ($$('#'+responsesId+' .ajax_responses_text')[0])
			{
				$$('#'+responsesId+' .ajax_responses_text')[0].show();
			}else if ($(this.text_id))
			{
				$(this.text_id).show();
			}
		}
	},
	
	hideError: function(responsesId)
	{
		// Data protection
		if (!$(responsesId)) return;

		// Hide error icon
		if ($$('#'+responsesId+' .ajax_responses_error')[0])
		{
			// Remove class name, ITIS
			if ($(responsesId).className.match(/ajax_responses_wrapper/))
			{
				$(responsesId).removeClassName('errors');
			}

			$$('#'+responsesId+' .ajax_responses_error')[0].hide();
		}else if ($(this.error_id))
		{
			$(this.error_id).hide();
		}
	},
	
	clearResponse: function(responsesId)
	{
		// Data protection
		if (!$(responsesId)) return;
		
		// Hide response text, ITIS
		if ($$('#'+responsesId+' .ajax_responses_text')[0])
		{
			// Clear class names, ITIS
			if ($(responsesId).className.match(/ajax_responses_wrapper/))
			{
				$(responsesId).removeClassName('successes');
				$(responsesId).removeClassName('infos');
				$(responsesId).removeClassName('notices');
				$(responsesId).removeClassName('errors');
			}

			$$('#'+responsesId+' .ajax_responses_text')[0].innerHTML = '';
		}else if ($(this.text_id))
		{
			$(this.text_id).innerHTML = '';
		}
		
		// Hide error/success indicator, ITIS
		this.hideResponse(responsesId);
		
		// Reset the response indicators
		this.error = false;
		this.success = false;
	},
	
	hideResponse: function(responsesId)
	{
		this.hideError(responsesId);
		this.hideSuccess(responsesId);
	},
	
	successHandler: function(self, cb, params)
	{
		return function(resp)
		{
			if (resp.status == "200")
			{
				if (params.responses.showSuccesses) eval(self).addSuccess((resp.responseText != '' ? resp.responseText : 'Success!'), params.responses.wrapperId);
			}else{
				if (params.responses.showErrors) eval(self).addError((resp.responseText != '' ? resp.responseText : 'Oops! We\'ve encountered an error. Please try again.'), params.responses.wrapperId);
			}

			eval(self).done(params.responses.wrapperId);

			if (resp.status == "200")
			{
				if (cb != null)
				{
					cb(resp.status, resp.responseText);
				}
			}
		}
	},
	
	failureHandler: function(self, cb, params)
	{
		return function(resp)
		{

			// No good... couldn't load a valid 2xx response
			if (params.responses.showErrors) eval(self).addError((resp.responseText != '' ? resp.responseText : 'Oops! There was a network failure. Please try again.'), params.responses.wrapperId);

			eval(self).done(params.responses.wrapperId);
		}
	},
	
	timeoutHandler: function(self, cb, params)
	{
		return function(resp)
		{
			// Timeout...
			if (params.responses.showErrors) eval(self).addError('Oops! Your request timed out. Please try again.', params.responses.wrapperId);

			eval(self).done(params.responses.wrapperId);
		}
	},
	
	completeHandler: function(self, cb, params)
	{
		return function(resp)
		{
		}
	},
	
	callInProgress: function(xmlhttp)
	{
		switch (xmlhttp.readyState) 
		{
			case 1:
			case 2:
			case 3:
				return true;
				break;

			// Case 4 and 0
			default:
				return false;
				break;
		}
	}
	
}); // End Class AjaxTransfer

var ajax = new AjaxTransfer('ajax'); // Pass the new class its own varname so that responders can access the global variable

// Register global responders that will occur on all AJAX requests - this is done to facilitate the onTimeout state for ajax calls
Ajax.Responders.register({
	onCreate: function(request)
	{
		request['timeoutId'] = window.setTimeout
		(
			function() 
			{
				// If we have hit the timeout and the AJAX request is active, abort it and let the user know
				if (ajax.callInProgress(request.transport))
				{
					request.transport.abort();

					// Run the onTimeout method if we set one up when creating the AJAX object
					if (request.options['onTimeout'])
					{
						request.options['onTimeout'](request.transport, request.json);
					}
				}
			},
			7000 // Timeout length in milliseconds
		);
	},

	onComplete: function(request) 
	{
		// Clear the timeout, the request completed ok
		window.clearTimeout(request['timeoutId']);
	}
});

