var Ajax = new function()
{
	var request;
	var onComplete

	function initializeRequest()
	{
		try
		{
			// if request is already initialized then do not recreate it
			if (request != null)
				return;
		
			// create XMLHttpRequest object (Opera 8.0+, Firefox, Safari)
			request = new XMLHttpRequest();
		}
		catch (exception)
		{
			// create XMLHttpRequest object (Internet Explorer)
			try
			{
				request = new ActiveXObject('Msxml2.XMLHTTP');
			}
			catch (exception)
			{
				try
				{
					request = new ActiveXObject('Microsoft.XMLHTTP');
				}
				catch (exception)
				{
					alert('Your browser does not support AJAX.');
					return;
				}
			}
		}
	}

	function onReadyStateChange()
	{
		try
		{
			// when response downloading is finished (readyState == 4)
			if (request.readyState == 4)
			{
				// if an error occured (status != 200, responseText == null) then throw an exception
				if (request.status != 200 || request.responseText == null)
					throw 'Invalid response.';
					
				// call onComplete callback
				if (onComplete != null)
					onComplete(decodeURIComponent(request.responseText));
			}
		}
		catch (exception)
		{
			// in case of exception display error message
			alert('Error during processing your request.');
			return;
		}
	}

	this.sendRequest = function(uri, parameters, onCompleteCallback)
	{		
		try
		{
			// try initialize request object
			initializeRequest();
			
			// if request is not initialized then abort sending
			if (request == null)
				return;
				
			// store onComplete callback
			onComplete = onCompleteCallback;
				
			// prepare the message which will be sent to the server
			var message = '';
			
			for (var name in parameters)
			{
				if (message != '')
					message += '&';
					
				if (parameters[name].constructor.toString().indexOf('Array') != -1)
				{
					// array parameter
					for (var i = 0; i < parameters[name].length; i++)
					{
						if (message != '')
							message += '&';	
						
						message += encodeURIComponent(name + '[]') + '=' + encodeURIComponent(parameters[name][i]);
					}
				}
				else
				{
					// regular parameter
					message += encodeURIComponent(name) + '=' + encodeURIComponent(parameters[name]);
				}
			}
			
			// send asynchronous HTTP request using POST method
			request.open('POST', uri, true);
			request.onreadystatechange = onReadyStateChange;				
			request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
			request.setRequestHeader('Content-length', message.length);
			request.setRequestHeader('Connection', 'close');
			request.send(message);
		}
		catch (exception)
		{
			// in case of exception display error message
			alert('Error during sending your request.');
			return;
		}
	}
	
	this.uploadFile = function(uri, fileId, onCompleteCallback)
	{	
		try
		{
			// get file element
			var fileElement = document.getElementById(fileId);
			
			// set file element's additional attributes
			fileElement.name = fileId;
			
			// create a div containing a form
			// and move the file element to the form
			var formDivElement;
			formDivElement = document.createElement('div');
			formDivElement.id = fileId + '_form_div';
			formDivElement.innerHTML = '<form id="' + fileId + '_form" action="' + uri + '" method="post" enctype="multipart/form-data" target="' + fileId + '_iframe" style="margin: 0; padding: 0">';
			fileElement.parentNode.insertBefore(formDivElement, fileElement);
			formDivElement.parentNode.removeChild(fileElement);
			document.getElementById(fileId + '_form').appendChild(fileElement);
			
			// create a div containing an iframe (form's target)
			// and set onComplete callback for the iframe
			var iframeDivElement;
			iframeDivElement = document.createElement('div');
			iframeDivElement.id = fileId + '_iframe_div';
			iframeDivElement.style.display = 'none';
			iframeDivElement.innerHTML = '<iframe id="' + fileId + '_iframe" name="' + fileId + '_iframe" src="about:blank" onload="Ajax.uploadComplete(\'' + fileId + '\');"></iframe>';
			document.body.appendChild(iframeDivElement);
			document.getElementById(fileId + '_iframe').onComplete = onCompleteCallback;
			
			// submit the form
			document.getElementById(fileId + "_form").submit();
		}
		catch (exception)
		{
			// in case of exception display error message
			alert('Error during sending your request.');
			return;
		}
	}
	
	this.uploadComplete = function(fileId)
	{
		try
		{
			// get iframe element
			var iframeElement = document.getElementById(fileId + '_iframe');
			
			// if iframe does not exists then return
			if (iframeElement == null)
				return;
			
			// get iframe's content document
			var contentDocument;
			
			if (iframeElement.contentDocument != null)
				contentDocument = iframeElement.contentDocument;
			else if (iframeElement.contentWindow != null)
				contentDocument = iframeElement.contentWindow.document;
			else
				contentDocument = window.frames[fileId + '_iframe'].document;

			// if iframe contains 'about:blank' then return
			if (contentDocument.location.href == 'about:blank')
				return;
			
			// get the response text
			var responseText = contentDocument.body.innerHTML;
			
			// get onComplete callback
			var onComplete = iframeElement.onComplete;

			// remove the div containing the iframe
			iframeElement.src = 'about:blank';
			document.body.removeChild(document.getElementById(fileId + '_iframe_div'));
			
			// get file element
			var fileElement = document.getElementById(fileId);
			
			// remove file element's additional attributes
			fileElement.name = null;
			
			// move the file element outside the form
			// and remove the div containing the form
			var formDivElement = document.getElementById(fileId + '_form_div');
			var formElement = document.getElementById(fileId + '_form');
			formElement.removeChild(fileElement);
			formDivElement.parentNode.insertBefore(fileElement, formDivElement);
			fileElement.parentNode.removeChild(formDivElement);

			// call onComplete callback
			if (onComplete != null)
				onComplete(decodeURIComponent(responseText));
		}
		catch (exception)
		{
			// in case of exception display error message
			alert('Error during processing your request.');
			return;
		}
	}
}