var MT4;

if (!MT4) {
    throw new Error("mt4.js não foi carregado");
}

MT4.util.ajax = {
	/**
	 * http.js: utilities for scripted HTTP requests
	 *
	 * From the book JavaScript: The Definitive Guide, 5th Edition,
	 * by David Flanagan. Copyright 2006 O'Reilly Media, Inc. (ISBN: 0596101996)
	 */

	// This is a list of XMLHttpRequest creation factory functions to try
	_factories: [
	    function() { return new XMLHttpRequest(); },
	    function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
	    function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
	],

	// When we find a factory that works, store it here
	_factory: null,

	/**
	 * Create and return a new XMLHttpRequest object.
	 * 
	 * The first time we're called, try the list of factory functions until
	 * we find one that returns a nonnull value and does not throw an
	 * exception.  Once we find a working factory, remember it for later use.
	 */
	newRequest: function() {
	    if (MT4.util.ajax._factory != null) return MT4.util.ajax._factory();
	
	    for(var i = 0; i < MT4.util.ajax._factories.length; i++) {
	        try {
	            var factory = MT4.util.ajax._factories[i];
	            var request = factory();
	            if (request != null) {
	                MT4.util.ajax._factory = factory;
	                return request;
	            }
	        }
	        catch(e) {
	            continue;
	        }
	    }
	
	    // If we get here, none of the factory candidates succeeded,
	    // so throw an exception now and for all future calls.
	    MT4.util.ajax._factory = function() {
	        throw new Error("XMLHttpRequest not supported");
	    }
	    MT4.util.ajax._factory(); // Throw an error
	},

	/**
	 * Use XMLHttpRequest to fetch the contents of the specified URL using
	 * an HTTP GET request.  When the response arrives, pass it (as plain
	 * text) to the specified callback function.
	 * 
	 * This function does not block and has no return value.
	 */
	getText: function(url, callback) {
	    var request = MT4.util.ajax.newRequest();
	    request.onreadystatechange = function() {
	        if (request.readyState == 4 && request.status == 200)
	            callback(request.responseText);
	    }
	    request.open("GET", url);
	    request.send(null);
	},

	/**
	 * Send an HTTP POST request to the specified URL, using the names and values
	 * of the properties of the values object as the body of the request.
	 * Parse the server's response according to its content type and pass
	 * the resulting value to the callback function.  If an HTTP error occurs,
	 * call the specified errorHandler function, or pass null to the callback
	 * if no error handler is specified.
	 * 
	 * Modificado por Pedro Manoel 29/08/07
	 * Adição do parâmetro opcional asynchronous, que diz se a requisição é síncrona ou assíncrona.
	 * Se não for especificado ou se for verdadeiro, a requisição será assíncrona. Caso seja falso,
	 * faz uma requisição síncrona
	 **/
	post: function(url, values, callback, errorHandler, asynchronous) {
		// se asynchronous não foi passado, abre um request assíncrono
		if (asynchronous == undefined) {
			asynchronous = true;
		}
		
	    var request = MT4.util.ajax.newRequest();
	    request.onreadystatechange = function() {
	        if (request.readyState == 4) {
	            if (request.status == 200) {
	                callback(MT4.util.ajax._getResponse(request));
	            }
	            else {
	                if (errorHandler) errorHandler(request.status,
	                                               request.statusText);
	                else callback(null);
	            }
	        }
	    }
        
	    request.open("POST", url, asynchronous);
	    // This header tells the server how to interpret the body of the request
	    request.setRequestHeader("Content-Type",
	                             "application/x-www-form-urlencoded");
	    // Encode the properties of the values object and send them as
	    // the body of the request.
	    request.send(MT4.util.ajax.encodeFormData(values));
        if (!asynchronous) {
            callback(MT4.util.ajax._getResponse(request));
        }
	},

	/**
	 * Encode the property name/value pairs of an object as if they were from
	 * an HTML form, using application/x-www-form-urlencoded format
	 */
	encodeFormData: function(data) {
	    var pairs = [];
	    var regexp = /%20/g; // A regular expression to match an encoded space
	
	    for(var name in data) {
	        var value = data[name].toString();
	        // Create a name/value pair, but encode name and value first
	        // The global function encodeURIComponent does almost what we want,
	        // but it encodes spaces as %20 instead of as "+". We have to
	        // fix that with String.replace()
	        var pair = encodeURIComponent(name).replace(regexp,"+") + '=' +
	            encodeURIComponent(value).replace(regexp,"+");
	        pairs.push(pair);
	    }
	
	    // Concatenate all the name/value pairs, separating them with &
	    return pairs.join('&');
	},

	/**
	 * Parse an HTTP response based on its Content-Type header
	 * and return the parsed object
	 */
	_getResponse: function(request) {
	    // Check the content type returned by the server
	    switch(request.getResponseHeader("Content-Type")) {
	    case "text/xml":
	        // If it is an XML document, use the parsed Document object
	        return request.responseXML;
	
	    case "text/json":
	    case "application/json": 
	    case "text/javascript":
	    case "application/javascript":
	    case "application/x-javascript":
	        // If the response is JavaScript code, or a JSON-encoded value,
	        // call eval() on the text to "parse" it to a JavaScript value.
	        // Note: only do this if the JavaScript code is from a trusted server!
	        return eval("(" + request.responseText + ")");
	
	    default:
	        // Otherwise, treat the response as plain text and return as a string
	        return request.responseText;
	    }
	},

	/**
	 * Send an HTTP GET request for the specified URL.  If a successful
	 * response is received, it is converted to an object based on the
	 * Content-Type header and passed to the specified callback function.
	 * Additional arguments may be specified as properties of the options object.
	 *
	 * If an error response is received (e.g., a 404 Not Found error),
	 * the status code and message are passed to the options.errorHandler
	 * function.  If no error handler is specified, the callback
	 * function is called instead with a null argument.
	 * 
	 * If the options.parameters object is specified, its properties are
	 * taken as the names and values of request parameters.  They are
	 * converted to a URL-encoded string with HTTP.encodeFormData() and
	 * are appended to the URL following a '?'.
	 * 
	 * If an options.progressHandler function is specified, it is
	 * called each time the readyState property is set to some value less
	 * than 4.  Each call to the progress handler function is passed an
	 * integer that specifies how many times it has been called.
	 *
	 * If an options.timeout value is specified, the XMLHttpRequest
	 * is aborted if it has not completed before the specified number
	 * of milliseconds have elapsed.  If the timeout elapses and an
	 * options.timeoutHandler is specified, that function is called with
	 * the requested URL as its argument.
	 **/
	get: function(url, callback, options) {
	    var request = MT4.util.ajax.newRequest();
	    var n = 0;
	    var timer;
	    if (options.timeout)
	        timer = setTimeout(function() {
	                               request.abort();
	                               if (options.timeoutHandler)
	                                   options.timeoutHandler(url);
	                           },
	                           options.timeout);
	
	    request.onreadystatechange = function() {
	        if (request.readyState == 4) {
	            if (timer) clearTimeout(timer);
	            if (request.status == 200) {
	                callback(MT4.util.ajax._getResponse(request));
	            }
	            else {
	                if (options.errorHandler)
	                    options.errorHandler(request.status,
	                                         request.statusText);
	                else callback(null);
	            }
	        }
	        else if (options.progressHandler) {
	            options.progressHandler(++n);
	        }
	    }
	
	    var target = url;
	    if (options.parameters)
	        target += "?" + MT4.util.ajax.encodeFormData(options.parameters)
	    request.open("GET", target);
	    request.send(null);
	}
};