
if ( !ajaxObjects )
{
	var ajaxCalls = {};
	var ajaxObjects = {};
	var ajaxCallQueue = [];
}

function OnSlowUpdateDim( containerId )
{
	if ( !$.browser.msie )
	{
		$( "#" + MakeSafeJquerySelector( containerId ) ).fadeTo('fast',0.45);
	}
}

function ServerCallComplete( callData, data )
{
	if ( callData.onSuccess )
	{
		callData.onSuccess( callData, data );
	}

	ajaxCalls[ callData.ajaxCall ].handler = false;

	ProcessAjaxCallQueue();
}

function ServerCall( ajaxCallId, params, onSuccess, onSlow )
{
	var ajaxCall = ajaxCalls[ ajaxCallId ];

	if ( ajaxCall.handler )
	{
		if ( !ajaxCall.allowMultipleCalls )
		{
			ajaxCall.handler.abort();
			ajaxCall.handler = false;
		}
	}

	if ( ajaxCall.millisecondDelay > 0 )
	{
		if ( ajaxCall.delayTimer )
		{
			clearTimeout( ajaxCall.delayTimer );
		}

		ajaxCall.delayTimer = setTimeout( function(){ ExecuteServerCall( ajaxCall, params, onSuccess, onSlow ) }, ajaxCall.millisecondDelay );
	}
	else
	{
		ExecuteServerCall( ajaxCall, params, onSuccess, onSlow );
	}
}

function ExecuteServerCall( ajaxCall, params, onSuccess, onSlow )
{
	var extraData = "";

	if ( ajaxCall.jsonPassThrough )
	{
		extraData = "param0=" + $.toJSON( params );
	}
	else
	{
		var p = 0;

		if ( params )
		{
			for( var x = 0; x < params.length; x++ )
			{
				extraData += "param" + p + "=" + params[x] + "&";
				p++;
			}
		}

	    for( var x = 0; x < ajaxCall.params.length; x++ )
		{
			extraData += "param" + p + "=" + ajaxCall.params[x] + "&";
			p++;
		}

		for( var x = 0; x < ajaxCall.jsVariables.length; x++ )
		{
			extraData += "param" + p + "=" + eval( ajaxCall.jsVariables[x] ) + "&";
			p++;
		}

		extraData += $("input,select,textarea").serialize();
	}

	var countOfCalls = 0;

    for ( var i in ajaxCalls )
    {
    	countOfCalls = Math.max( countOfCalls, i );
	}

	var countOfObjects = 0;

    for ( var i in ajaxObjects )
    {
    	countOfObjects++;// Math.max( countOfObjects, i );
	}

	var ajaxCallId = ajaxCall.callId;

	var onSuccessHandler = ajaxCall.onSuccess;

	if ( onSuccess )
	{
		if ( ajaxCall.onSuccess )
		{
			onSuccessHandler = function( call, data ){ onSuccessHandler( call, data ); onSuccess( call, data ); };
		}
		else
		{
			onSuccessHandler = onSuccess;
		}
	}

	var onSlowHandler = ajaxCall.onSlow;

	if ( onSlow )
	{
		if ( ajaxCall.onSlow )
		{
			onSlowHandler = function( call, data ){ onSlowHandler( call, data ); onSlow( call, data ); };
		}
		else
		{
			onSlowHandler = onSlow;
		}
	}

	ajaxCallQueue[ ajaxCallQueue.length ] =
	{
			ajaxCall: ajaxCallId,
			ajaxParams: params,
			executed: false,
			container: ajaxCall.containerId,
			onSuccess: onSuccessHandler,
			onBegin: ajaxCall.onBegin,
			onSlow: onSlowHandler,
			contentType: ajaxCall.contentType,
			form: ajaxCall.form,
			objectId: ajaxCall.objectId,
			containerId: ajaxCall.containerId,
			functionName: ajaxCall.functionName,
			countOfCalls: countOfCalls,
			countOfObjects: countOfObjects,
			timer: null,
			extraData: extraData
	};

	ProcessAjaxCallQueue();
}

function ProcessAjaxCallQueue()
{
	for( var i = 0; i < ajaxCallQueue.length; i++ )
	{
		var call = ajaxCallQueue[ i ];

		if ( call.executed )
		{
			continue;
		}

		if ( ajaxCalls[ call.ajaxCall ].handler )
		{
			continue;
		}

		ajaxCallQueue[ i ].executed = true;

		MakeAjaxCall( call );
	}
}

function MakeAjaxCall( callData )
{
	clearTimeout( callData.timer );

	if ( callData.onSlow )
	{
		callData.timer = setTimeout( callData.onSlow, 200 );
	}
	else
	{
		if ( callData.container != "" )
		{
			callData.timer = setTimeout( "OnSlowUpdateDim( '" + callData.container + "' )", 100 );
		}
	}

	var ajaxUrl = "/ajax/server-call";
	var inputData = "pg-ajax=1&object-data=" + ajaxObjects[ callData.objectId ] + "&ct=" + callData.contentType + "&frm=" + callData.form + "&f=" + callData.functionName + "&containerId=" + callData.container + "&ac=" + callData.countOfCalls + "&oc=" + callData.countOfObjects + "&" + callData.extraData;
	var ajaxCall = ajaxCalls[ callData.ajaxCall ];

	ajaxCall.handler = $.ajax(
	{
  		type: 'POST',
		url: ajaxUrl,
		data: inputData,
		dataType: 'text',
		success: function( data )
			{
				clearTimeout( callData.timer );

				if ( callData.container != '' )
				{
					var selector = "#" + MakeSafeJquerySelector( callData.container );

					$( selector ).html( data );

					if ( !$.browser.msie )
					{
						$( selector ).fadeTo('fast',1);
					}
				}

				if ( callData.contentType == 'json' )
				{
					data = eval( '(' + data + ')' );
				}

				ServerCallComplete( callData, data );

				if ( callData.contentType == 'js' )
				{
					eval( data );
				}
			},
		error: function( request, textStatus, errorThrown )
		{
			alert( request.responseText );
		}

	});

	if ( ajaxCall.onBegin )
	{
		callData.onBegin( callData );
	}
}

var applicationEventHooks = {};

function SendApplicationEventToServer( eventCode, objectId, data, callBack )
{
	// All application objects are piped through a single ajax call definition.
	// This call allows multiple simultaneous requests, however we don't want
	// to do that if the event name is the same. We have to check this manually.

	for( var i = 0; i < ajaxCallQueue.length; i++ )
	{
		var call = ajaxCallQueue[ i ];

		if ( call.ajaxCall != "SendClientSideEvent" )
		{
			continue;
		}

		if ( ( call.ajaxParams[ 0 ] == eventCode ) && ( call.ajaxParams[ 1 ] == objectId ) )
		{
			if ( ajaxCalls[ call.ajaxCall ].handler )
			{
				ajaxCalls[ call.ajaxCall ].handler.abort();
				ajaxCalls[ call.ajaxCall ].handler = false;
			}
		}

		if ( !call.executed )
		{
			// Neutralise it.
			call.executed = true;
		}
	}

	var combinedData = [ eventCode, objectId ];

	if ( data )
	{
		combinedData = $.merge( combinedData, data );
	}

	ServerCall( 'SendClientSideEvent', combinedData, function( callName, response )
	{
		var dom = $( "<div>" + response + "</div>" );

		dom.find( '.app-update' ).each( function()
		{
			var id = $( this )[0].id;
			var parts = id.split( '_' );

			var objectId = parts[ 1 ];

			$( "#" + MakeSafeJquerySelector( objectId ) ).html( $( this ).html() );
		} );

		dom.filter( 'script' ).each( function()
		{
			eval( $( this ).html() );
		} );

		$( '.dimmed' ).css('opacity', 1);

		if ( callBack )
		{
			callBack();
		}
	},
	function()
	{
		var hooks = applicationEventHooks[ eventCode + objectId ];

		for( var i = 0; i < hooks.length; i++ )
		{
			var targetId = hooks[ i ];

			if ( targetId != objectId )
			{
				$( '#PgAjax-' + hooks[ i ] ).fadeTo( 0, 0.5 ).addClass('dimmed');
			}
		}
	} );
}
