// ajax_async.js

// uses array.js
// uses param_maker.js
// uses id_generator.js



function AjaxCreateRequestObject()
{
	if ( window.XMLHttpRequest)
		return new XMLHttpRequest();
	else
	if ( window.ActiveXObject)
		return new ActiveXObject( "Microsoft.XMLHTTP");
	return null;
}

function AjaxIsSupported()
{
	if ( AjaxCreateRequestObject() == null)
		return false;
	return true;
}

function AjaxIsStateReady( readyState)
{
	if (( readyState == 4)||( readyState=="complete"))
		return true;
	return false;
}

function AjaxIsStatusOK( status)
{
	if ( status == 200)
		return true;
	return false;
}

function AjaxMethodName( bPost)
{
	if ( bPost)
		return 'POST';
	return 'GET';
}

function AjaxConvertParamValue( strText)
{
	strText = strText.toString();
	var reg = /(&)(?!amp;)/g;
	return strText.replace( reg, '&amp;');
}

function CAjaxParamValueConverter()
{
	this.Convert = AjaxConvertParamValue;
}

//function AjaxSendRequest( strUrl, bPost, strPostData, strId, strOnDataFnName, strOnBadStatusFnName)
//{
//	var ajax = AjaxCreateRequestObject();
//	if ( ajax == null)
//	{
//		//ToDo...
//		alert("Your browser doesn't support AJAX.");
//	}
//	else
//	{
//		ajax.onreadystatechange = function() 
//		{
//			if ( AjaxIsStateReady( ajax.readyState))
//			{
//				if ( AjaxIsStatusOK( ajax.status))
//					eval( strOnDataFnName+"( '"+strId+"')"); 
//				else
//				if ( strOnBadStatusFnName)
//					eval( strOnBadStatusFnName+"( '"+strId+"')"); 
//			}
//		}
//		ajax.open( AjaxMethodName( bPost), strUrl, true);
//		if ( !bPost)
//			strPostData = null;
//		ajax.send( strPostData);
//	}
//}
//
//function AjaxSendRequestWithParam( strUrl, bPost, paramMaker, strId, strOnDataFnName, strOnBadStatusFnName)
//{
//	var ajax = AjaxCreateRequestObject();
//	if ( ajax == null)
//	{
//		//ToDo...
//		alert("Your browser doesn't support AJAX.");
//	}
//	else
//	{
//		ajax.onreadystatechange = function() 
//		{
//			if ( AjaxIsStateReady( ajax.readyState))
//			{
//				if ( AjaxIsStatusOK( ajax.status))
//					eval( strOnDataFnName+"( '"+strId+"')"); 
//				else
//				if ( strOnBadStatusFnName)
//					eval( strOnBadStatusFnName+"( '"+strId+"')"); 
//			}
//		}
//		var strPostData = null;
//		var strParamString = paramMaker.ParamString( new CAjaxParamValueConverter());
//		if ( strParamString.length > 0)
//		{
//			if ( bPost)
//				strPostData = strParamString;
//			else
//			{
//				if ( strUrl.indexOf( '?') < 0)
//					strUrl += '?';
//				else
//					strUrl += '&';
//				strUrl += strParamString;
//			}
//		}
//
//		ajax.open( AjaxMethodName( bPost), strUrl, true);
//		ajax.send( strPostData);
//	}
//}

//function CAjaxRequestInformation( ajax, userData)
//{
//	this.m_ajax = ajax;
//	this.m_userData = userData;
//}

function CAjaxRequestHash( nMaxRequestId)
{
	this.m_hashRequestInformation = new CHash();
	this.m_idGenerator = new CIdGenerator( nMaxRequestId);

	this.Clear = CAjaxRequestHash;

	this.Ajax = function( nRequestId)
	{
		var requestInformation = this.m_hashRequestInformation.Item( nRequestId);
		if ( requestInformation)
			return requestInformation.m_ajax;
		return null;
	}

	this.UserData = function( nRequestId)
	{
		var requestInformation = this.m_hashRequestInformation.Item( nRequestId);
		if ( requestInformation)
			return requestInformation.m_userData;
		return null;
	}

	this.SetUserData = function( nRequestId, userData)
	{
		var requestInformation = this.m_hashRequestInformation.Item( nRequestId);
		if ( requestInformation)
			requestInformation.m_userData = userData;
	}

	this.PutAjax = function( ajax, userData)
	{
		var nRequestId = this.m_idGenerator.NextId();
		if ( nRequestId > 0)
		{
			this.m_idGenerator.OccupeId( nRequestId);
			this.m_hashRequestInformation.Set( nRequestId, new this.CAjaxRequestInformation( ajax, userData));
		}
		return nRequestId;
	}

	this.RemoveRequest = function( nRequestId)
	{
		this.m_hashRequestInformation.Del( nRequestId);
		this.m_idGenerator.FreeId( nRequestId);
	}

	this.CAjaxRequestInformation = function( ajax, userData)
	{
		this.m_ajax = ajax;
		this.m_userData = userData;
	}
}

var s_ajaxRequestHash = new CAjaxRequestHash( 1000); // Maximum number of concurent AJAX requests

//function AjaxSetRequestUserData( nRequestId, userData)
//{
//	alert( 'AjaxSetRequestUserData( '+nRequestId+', '+userData+')');
//	s_ajaxRequestHash.SetUserData( nRequestId, userData);
//}

function AjaxGetRequestUserData( nRequestId)
{
	return s_ajaxRequestHash.UserData( nRequestId);
}

function AjaxGetRequestObject( nRequestId)
{
	return s_ajaxRequestHash.Ajax( nRequestId);
}

function AjaxAbortRequest( nRequestId)
{
	var ajax = AjaxGetRequestObject( nRequestId);
	if ( ajax)
	{
		s_ajaxRequestHash.RemoveRequest( nRequestId);
		ajax.abort();
	}
}

/// @param paramMaker type is #CParamMaker can be null or false
/// @return request id. It is useful to set user data for request.
function AjaxSendRequest( strUrl
												, bPost
												, paramMaker // can be null or false
												, userData // can be null or false
												, strOnDataFnName // can be null or false
												, strOnBadStatusFnName // can be null or false
												)
{
	var nRequestId = false;
	var ajax = AjaxCreateRequestObject();
	if ( ajax == null)
	{
	}
	else
	{
		nRequestId = s_ajaxRequestHash.PutAjax( ajax, userData);
		if ( nRequestId > 0)
		{
			ajax.onreadystatechange = function()
			{
				if ( AjaxIsStateReady( ajax.readyState))
				{
					if ( AjaxGetRequestObject( nRequestId))
					{
						if ( AjaxIsStatusOK( ajax.status))
						{
							if ( strOnDataFnName)
								eval( strOnDataFnName+"( "+nRequestId+")");
						}
						else
						if ( strOnBadStatusFnName)
							eval( strOnBadStatusFnName+"( "+nRequestId+")");

						s_ajaxRequestHash.RemoveRequest( nRequestId);
					}
				}
			}

			var strPostData = null;
			if ( paramMaker)
			{
				var strParamString = paramMaker.ParamString( new CAjaxParamValueConverter());
				if ( strParamString.length > 0)
				{
					if ( bPost)
						strPostData = strParamString;
					else
					{
						if ( strUrl.indexOf( '?') < 0)
							strUrl += '?';
						else
							strUrl += '&';
						strUrl += strParamString;
					}
				}
			}

			ajax.open( AjaxMethodName( bPost), strUrl, true);
			if ( bPost)
				ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
			ajax.send( strPostData);
		}
	}
	return nRequestId;
}
