/**
 * Create an AJAX object for sending AJAX requests and receiving given responses.
 * 
 * Part of the Scout Portal Toolkit
 * Copyright 2004 Internet Scout Project
 * http://scout.wisc.edu
 *
 * @author Tim Baumgard
 */
function AJAX(source) {

    /**
     * @var object Request hold the request object
     * @var string Response hold the response of a request
     * @var string File file name of the remote file
     * @var object Cache stores entries that have been cached
     * @var int CacheSize current size of the cache
     * @var int CacheMax maximum number of entries allowed in the cache
     */
    var Request;
    var Response;
    var File;
    var Cache;
    var CacheSize;
    var CacheMax;
    
    /**
     * --- PUBLIC METHODS ---
     */

    /**
     * Get the response text.
     *
     * @author Tim Baumgard
     * @return string return the AJAX response
     */
    this.getResponse = function() {    
        return Response;
    }

    /**
     * Set the file name of the remote file that will be called on a send request.
     *
     * @author Tim Baumgard
     * @param string source source file name
     */
    this.setFile = function(source) {
        // Check input, return if necessary
        if ("string" !== typeof source) {
            return;
        }
        
        File = source;
    }
    
    /**
     * Set a new maximum cache size.
     *
     * @author Tim Baumgard
     * @param int size new cache size
     */
    this.setMaxCacheSize = function(size) {
        // Set cache size if input is valid
        if ("string" === typeof size || "number" === typeof size) {
            CacheMax = parseInt(size);
        }
    }
    
    /**
     * Send an AJAX request to the remote file.
     *
     * @author Tim Baumgard
     * @param object parameters get parameters in object form
     * @param string parameters string get query
     * @param boolean cache true to get result from cache/cache result from AJAX
     * @param boolean async whether the call should be asynchronous
     */
    this.sendRequest = function(parameters, cache, async) {
        // Initialize get query, reset last response
        var query = File;
        if ("undefined" === typeof async || "boolean" !== typeof async) {
            async = false;
        }

        // Turn parameter object or string into get query
        if ("object" === typeof parameters) {
            // Add each key/value to the query
            query += "?"
            for (var name in parameters) {
                query += name + "=" + parameters[name] + "&";
            }
            
            // Use cache as response, return
            if (cache === true && "undefined" !== typeof Cache[query]) {
                Response = Cache[query];
                CacheSize++;
                return;
            }
        } else if ("string" === typeof parameters) {
            query += "?" + parameters;
        }

        // Reset request object for use IE
        if (navigator.appName == "Microsoft Internet Explorer") {
            Request = createRequestObject();
        }

        // Fix for Mozilla. Synchronous request (Moz) requires onload vs. onreadystatechange
        try {
            // Ugly bugfix (tries to detect browser) for Opera onload incompatibility
            if (navigator.userAgent.toLowerCase().indexOf("opera") != -1) {
                throw "opera";
            }        
            
            // Set up onload
	        Request.onload = function(e) {
	    	    var event = window.event ? window.event : e;
                var request = ("undefined" !== typeof event.target) ? event.target : event.srcElement;
                workWithResponse(request.responseText, query, cache);
            }
        } catch(e) {
            // Set up readystatechange
            Request.onreadystatechange = function() {
                if (Request.readyState == 4) {
                    workWithResponse(Request.responseText, query, cache);
                }
            };
        }
        
        // Send query (3rd param for open MUST be false, we need synchronous request)
        Request.open("get", query, async);
        Request.send(null);
    }
    
    /**
     * PRIVATE METHODS
     */
    
    /**
     * Function created to provide one location for working with response. Only needed because
     * Mozilla doesn't use onreadystatechange with synch requests at the moment.
     *
     * @author Tim Baumgard
     * @param string response response from the AJAX request
     * @param string query query vars sent via AJAX request, used for caching
     * @param boolean cache true to get result from cache/cache result from AJAX
     */
    function workWithResponse(response, query, cache) {
        // Save response
        Response = response;

        // Work with the cache
        if (cache === true) {
            // Remove cache entry if too large
            if (CacheSize >= CacheMax) {
                for (var i in Cache) {
                    delete Cache[i];
                    CacheSize--;
                    break;
                }
            }
                    
            // Cache if necessary
            Cache[query] = response;
        }
    }
    
     
    /**
     * Create a request object for use in an AJAX request.
     *
     * @author Tim Baumgard
     * @return object new request object
     */
    function createRequestObject() {
        // Return ActiveXObject if IE, else XML request
        if (navigator.appName == "Microsoft Internet Explorer") {
            return new ActiveXObject("Microsoft.XMLHTTP");
        } else {
            return new XMLHttpRequest();
        }
    }
    
    /**
     * Constructor: set up the AJAX object.
     *
     * @author Tim Baumgard
     * @param string source remote file's name, if given
     */
     
        // Initialize private variables
        this.setFile(source);
        Request = createRequestObject();
        Response = "";
        Cache = {};
        CacheMax = 20;
        CacheSize = 0;
        
}