var g_ie = false;
var MAX_CONCURRENT_REQUESTS = 2;
var g_request_queue = new Array();
var g_current_requests = new Array();

function XML_request( id, url, data, result_handler, force_post, callback_data )
{
    var m_id = id;
    var m_url = url;
    var m_data = data;
    var m_force_post = force_post;
    var m_req = null;
    var m_result_handler = result_handler;
    var m_callback_data = callback_data;

    this.Get_id = function()
    {
        return m_id;
    }

    if( window.XMLHttpRequest ) {
        try {
            m_req = new XMLHttpRequest();
        } catch( e ) {
            m_req = null;
        }
    } else if( window.ActiveXObject ) {
        try {
            m_req = new ActiveXObject( "Msxml2.XMLHTTP" );
            g_ie = true;
        } catch( e ) {
            try {
                m_req = new ActiveXObject( "Microsoft.XMLHTTP" );
                g_ie = true;
            } catch( e ) {
                m_req = null;
            }
        }
    }

    if( m_req == null ) {
        m_result_handler( id, false, "noxml", m_callback_data );
        return;
    }

    this.State_changed = function()
    {
        if( m_req.readyState != 4 ) {
            return;
        } else if( m_req.status != 200 ) {
            Request_completed( m_id );
            m_result_handler( id, false, m_req.statusText, m_callback_data );
            return;
        }

        Request_completed( m_id );
        if( m_req.responseText.indexOf( "debug" ) == 0 ) {
            alert( m_req.responseText.substr( 5 ) );
        }
        m_result_handler( m_id, true, m_req.responseText, m_callback_data );
    }

    if( url == null ) {
        m_result_handler( id, false, "nourl" );
        return;
    }

    m_req.onreadystatechange = this.State_changed;
    this.Send = function()
    {
        if( data.length > 128 || m_force_post ) {
            m_req.open( "POST", SITE_ROOT + m_url, true );
            m_req.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
            m_req.send( m_data );
        } else {
            m_req.open( "GET", SITE_ROOT + m_url + "?" + m_data, true );
            m_req.send( "" );
        }
    }

    Add_request( this );
    Trigger_requests();
}

function Add_request( request )
{
    for( var i = 0; i < g_request_queue.length; i++ ) {
        if( g_request_queue[i].Get_id() == request.Get_id() ) {
            var old_request = g_request_queue[i];
            g_request_queue.splice( i, 1 );
            delete old_request;
            break;
        }
    }

    g_request_queue.push( request );
}

function Trigger_requests()
{
    if( g_current_requests.length < MAX_CONCURRENT_REQUESTS ) {
        if( g_request_queue.length == 0 ) {
            return;
        }

        var request = g_request_queue.shift();
        for( var i = 0; i < g_current_requests.length; i++ ) {
            if( g_current_requests[i].Get_id() == request.Get_id() ) {
                g_request_queue.unshift( request );
                return;
            }
        }
        g_current_requests.push( request );
        request.Send();
    }
}

function Request_completed( request_id )
{
    for( var i = 0; i < g_current_requests.length; i++ ) {
        if( g_current_requests[i].Get_id() == request_id ) {
            var request = g_current_requests[i];
            g_current_requests.splice( i, 1 );
            delete request;
            break;
        }
    }
    Trigger_requests();
}

var g_xml_pass = false;

function XML_test_result( id, result, text )
{
    if( id != "xml_test" ) {
        return;
    }
    if( !result ) {
        if( text == "noxml" ) {
            // User does not have the xml support.
        } else if( text == "nourl" ) {
            // Allow page loading.
            g_xml_pass = true;
        }
    }
}

if( g_test_capabilities ) {
    // Test out if we are able to do XML requeusts.
    var g_xml_test = new XML_request( "xml_test", null, null, XML_test_result, false );

    // We should fail immediately.
    if( !g_xml_pass ) {
        Fatal_error( "async" );
    }

    delete g_xml_test;
}
