
if ( !ajaxObjects )
{
	var ajaxCalls = {};
	var ajaxObjects = {};
	var ajaxCallQueue = [];
}

function OnSlowUpdateDim( containerId )
{
	if ( !$.browser.msie )
	{
		$( "#" + MakeSafeJquerySelector( containerId ) ).fadeTo('fast',0.45);
	}
}

function ServerCallComplete( callData, data )
{
	var result = false;

	if ( callData.onSuccess )
	{
		result = callData.onSuccess( callData, data );
	}

	ajaxCalls[ callData.ajaxCall ].handler = false;

	ProcessAjaxCallQueue();

	return result;
}

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 in params )
			{
                if ( parseInt(x) == x )
                {
				    extraData += "param" + p + "=" + params[x] + "&";
                    p++;
                }
                else
                {
                    extraData += x + "=" + params[ x ] + "&";
                }
			}
		}

	    for( var x in ajaxCall.params.length )
		{
            if ( parseInt( x ) == x )
            {
                extraData += "param" + p + "=" + ajaxCall.params[x] + "&";
                p++;
            }
            else
            {
                extraData += x + "=" + ajaxCall.params[ x ] + "&";
            }
		}

		for( var x = 0; x < ajaxCall.jsVariables.length; x++ )
		{
			extraData += "param" + p + "=" + eval( ajaxCall.jsVariables[x] ) + "&";
			p++;
		}

		if ( ajaxCall.appSessionKey )
		{
			extraData += "app-session-key=" + ajaxCall.appSessionKey + "&";
			extraData += "app-session-data=" + escape( ajaxObjects[ ajaxCall.appSessionKey ] ) + "&";
		}

		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;

	if ( onSuccess )
	{
		if ( ajaxCall.onSuccess )
		{
			onSuccessHandler = function( call, data ){ ajaxCall.onSuccess( call, data ); onSuccess( call, data ); };
		}
		else
		{
			onSuccessHandler = onSuccess;
		}
	}
	else
	{
		onSuccessHandler = ajaxCall.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,
			inProgress: false,
			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()
{
	var inProgress = false;

	for( var i = 0; i < ajaxCallQueue.length; i++ )
	{
		var call = ajaxCallQueue[ i ];

		if ( call.inProgress )
		{
			inProgress = true;
		}

		if ( call.executed )
		{
			continue;
		}

		if ( ajaxCalls[ call.ajaxCall ].handler )
		{
			continue;
		}

		ajaxCallQueue[ i ].executed = true;

		MakeAjaxCall( call );

		if ( call.inProgress )
		{
			inProgress = true;
		}
	}

	if ( inProgress )
	{
		$( 'body' ).addClass( 'ajax-in-progress' );
	}
	else
	{
		$( 'body' ).removeClass( 'ajax-in-progress' );
	}
}

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 ];

	callData.inProgress = true;

	ajaxCall.handler = $.ajax(
	{
  		type: 'POST',
		url: ajaxUrl,
		data: inputData,
		dataType: 'text',
        async: callData.async,
		success: function( data )
			{
				callData.inProgress = false;
				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 + ')' );
				}

				var result = ServerCallComplete( callData, data );

				callData.result = result;

				if ( callData.contentType == 'js' )
				{
					eval( data );
				}

				ProcessAjaxCallQueue();
			},
		error: function( request, textStatus, errorThrown )
		{
			callData.inProgress = false;
			alert( request.responseText );

			ProcessAjaxCallQueue();
		}

	});

	if ( ajaxCall.onBegin )
	{
		callData.onBegin( callData );
	}

	ProcessAjaxCallQueue();
}

var applicationEventHooks = {};

function SendApplicationEventToServer( eventCode, objectId, data, dimTargets, callBack, async, sessionKey )
{
    if ( typeof async == "undefined" )
    {
        async = true;
    }

	// 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" + "_" + sessionKey )
		{
			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 );
	}

    ajaxCalls[ "SendClientSideEvent_" + sessionKey ].async = async;

	ServerCall( 'SendClientSideEvent_' + sessionKey, 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()
	{
		if( typeof( dimTargets ) != 'undefined' )
		{
			for( var i = 0; i < dimTargets.length; i++ )
			{
				$( dimTargets[ i ] ).fadeTo( 0, 0.5 ).addClass('dimmed');
			}
		}

		var hooks = applicationEventHooks[ eventCode + objectId ];

		if( hooks != undefined )
		{
			for( var i = 0; i < hooks.length; i++ )
			{
				var targetId = hooks[ i ];

				if ( targetId != objectId )
				{
					$( '#PgAjax-' + hooks[ i ] ).fadeTo( 0, 0.5 ).addClass('dimmed');
				}
			}
		}
	} );
}
