function Ajax()
{
    this.pool = new Array();
    this.index = 0;
    this.method = "POST";
    this.async = true;
    this.uri = '/ajax/call';
    this.callback = null;
    this.stored_target = null;
    this.stored_action = null;
    this.upload_frame_name = null;
    this.upload_frm = null;
    this.upload_div = null;
    this.cache_key = null;
    
    
    this.instance = function()
    {
    	var retVal;
    	for (var i=0; i<arguments.length; i++)
    	{
    		try{
    			retVal = arguments[i]();
    			break;
    		}
    		catch (e) {}
    	}
    	return retVal;
    }
    
    this.upload = function(frm)
    {
        this.upload_frame_name = 'f' + Math.floor(Math.random() * 99999);
        var div = document.createElement('DIV');
        div.innerHTML = '<iframe style="display:none" src="about:blank" id="'+this.upload_frame_name+'" name="'+this.upload_frame_name+'" onload="ajaxUploadComplete(\''+this.upload_frame_name+'\')"></iframe>';
        document.body.appendChild(div);
        this.upload_div = div;
        
        this.upload_frm = frm;
        
        this.stored_target = frm.getAttribute('target');
        this.stored_action = frm.getAttribute('action');
        frm.setAttribute('target', this.upload_frame_name);
        frm.setAttribute('action', this.uri+"?method=uploadFile&plain=1");
    }
    
    this.uploadComplete = function()
    {
        this.upload_frm.setAttribute("target", this.stored_target);
        this.upload_frm.setAttribute("action", this.stored_action);
        var elem = document.getElementById(this.upload_frame_name);
        if (elem.contentDocument)
        {
            var res = elem.contentDocument.body.innerHTML;
        }
        else if (elem.contentWindow)
        {
            var res = elem.contentWindow.document.body.innerHTML;
        }
        else
        {
            var res = window.frames[this.upload_frame_name].document.body.innerHTML;
        }
        uploadCallBack(res);
    }
    
    this.create = function()
    {
        this.index = this.pool.length;
        this.pool[this.index] = this.instance(
          function() {return new ActiveXObject('Msxml2.XMLHTTP')},
          function() {return new ActiveXObject('Microsoft.XMLHTTP')},
          function() {return new XMLHttpRequest()}
        ) || false;
        return this.index;
    }
    
    this.abort = function(n)
    {
        if (this.pool[n])
        {
            this.pool[n].abort();
        }
    }
    
    this.call = function(n, method, args)
    {
        if (this.cache_key != null)
        {
            var res = cache_get('ajax_'+method, args[this.cache_key]);
            if (res)
            {
                return res;
            }
        }
        if (!n)
        {
            n = this.create();
        }
        var data = "";
        if (this.method == "GET")
        {
            this.uri += this.uri.indexOf("?") == -1 ? "?" : "&";
        }
        
        data += "method=" + encodeURIComponent(method);
        for (var key in args)
        {
            data += "&args[" + encodeURIComponent(key) + "]=" + encodeURIComponent(args[key]);
        }
        data += "&rnd=" + new Date().getTime();
        
    	this.pool[n].open(this.method, this.uri, this.async);
    	if (this.method == "POST") 
    	{
    		this.pool[n].setRequestHeader("Method", "POST " + this.uri + " HTTP/1.1");
    		this.pool[n].setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    	}
    	if (this.async)
    	{
    	    var ajaxObj = this.pool[n];
    	    var callback = this.callback;
    	    var cache_key = this.cache_key;
    		this.pool[n].onreadystatechange = function() 
    		{
    			if (ajaxObj.readyState != 4)
    			{
    				return;
                }
    			
    			var data = ajaxObj.responseText;
    			if (cache_key != null)
    			{
    			    cache_set('ajax_'+method, args[cache_key], data);
    			}
    			if (callback)
    			{
   				     callback(data);
    			}
    		}
    	}
    	this.pool[n].send(data);
    	if (!this.async)
    	{
    		var data = this.pool[n].responseText;
    		if (this.cache_key != null)
    		{
    		    cache_set('ajax_'+method, args[this.cache_key], data);
    		}
    		if (data.substring(0, 3) == '-1:')
    		{
    		    alert('An error occured during remote call: ' + data.substring(3));
    		    return false;
    		}
    		
    		
    		if (this.callback)
    		{
    		    this.callback(data);
    		}
    		else
    		{
    		    return data;
    		}
    	}
    }
}

function ajaxCall(method, args, callback, override)
{
    if (!window.AJAX)
    {
        window.AJAX = new Ajax();
    }
    window.AJAX.callback = callback;
    if (override)
    {
        for (var key in override)
        {
            window.AJAX[key] = override[key];
        }
    }
    return window.AJAX.call(0, method, args);
}

function ajaxSyncCall(method, args, cache_key)
{
    return ajaxCall(method, args, null, {async:false, 'cache_key': cache_key});
}

function ajaxUpload(frm)
{
	if (typeof progressCallBack == 'function' )
	{
		progressCallBack();
	}  
    if (!window.AJAX)
    {
        window.AJAX = new Ajax();
    }
    window.AJAX.upload(frm);
    frm.submit();
}

function ajaxUploadComplete(id)
{
    if (!window.AJAX)
    {
        return;
    }
    window.AJAX.uploadComplete();
}