/**
 * Class Ajax
 *
 * Class responsible for interacting with the server
 * sending requests asynchronous Ajax
 */

TrueWizard.Ajax = new TrueWizard.Class(function()
{
    /**
     * Method that is used to make calls
     */
    this.method  = null;

    /**
     * Url of which should be known
     */
    this.url     = null;

    /**
     * Headers defaults that will be sent
     */
    this.headers = {
        'X-Requested-With' : 'XMLHttpRequest',
        'X-Ajax-Engine'    : 'TrueWizard'
    };

    /**
     * Class Initializator
     * Sete method and the url to be used to interact with the server
     *
     * @param  String method = The HTTP method that was used to send information
     * @param  String url    = The url of which should be known
     * @return Object TrueWizard.Ajax
     */

    this.init = function( method, url )
    {
        this.method   = method;
        this.url      = url;

        return this;
    };

    /**
     * Save a header that will be sent when it launched the Ajax request
     * If there is already a header with that name, overrides it
     *
     * @param  String name  = Header Name
     * @param  String value = Header Content
     * @return Object TrueWizard.Ajax
     */
    this.setHeader = function( name, value )
    {
        this.headers[ name ] = value;
        return this;
    };

    /**
     * Send HTTP headers to make the request
     *
     * @return Object TrueWizard.Ajax
     */
    this.sendHeaders = function()
    {
        for ( var name in this.headers ) {
            this.xmlHttp.setRequestHeader( name, this.headers[ name ] );
        }
        return this;
    };

    /**
     * Create the XMLHttpRequest object and returns it
     *
     * @return void
     */
    this.XMLHttpRequest = function()
    {
        // For Firefox, Safari, Opera, Google Chrome and every standard browser
        if ( null != window.XMLHttpRequest ) {
            return new XMLHttpRequest;
        }
        else {
            // For Internet Explorer
            var candidates = [ 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ];
            var xmlHttp    = null;

            for ( var i = 0; i < candidates.length; i++ ) {
                try {
                    xmlHttp = new ActiveXObject( candidates[ i ] );
                    return xmlHttp;
                }
                catch( e ) {
                }
            }
        }
    };

    /**
     * It applies to objectData format so it can be sent
     *
     * @param  Object objectData = Associative array with data that will be sent
     *
     * @return String;
     */
    var formatData = function( objectData )
    {
        var data = [];

        for ( var key in objectData ) {
            data.push( key + '=' + encodeURIComponent( objectData[ key ] ) );
        }

        return data.join('&');
    };

    /**
     * Check if the string passed as argument is a valid json value.
     * If so, it executes and returns the resulting object
     *
     * @param  String json = a json string
     * @return Object | String
     */
    var evalJson = function( json )
    {
        if ( /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test( json ) ) {
            return eval('(' + json + ')');
        }

        return json;
    };

    /**
     * Ajax runs the request, using the url and the method previously defined
     * When complete, is called the callback function
     *
     * @param  Object   data     = Information that will be sent
     * @param  Function callback = unction to execute when the request is completed
     *                            this function takes as argument the result returned json
     *
     * @return Object TrueWizard.Ajax
     */

    this.request = function( data, callback )
    {
        this.xmlHttp = this.XMLHttpRequest();
        this.xmlHttp.open( this.method, this.url, true );
        this.sendHeaders();

        var self = this;

        this.xmlHttp.onreadystatechange = function()
        {
            if ( self.xmlHttp.readyState == 4 ) {
                callback.call( self, evalJson( self.xmlHttp.responseText ) );
            }
        };

        if ( this.method.toLowerCase() == 'post' ) {
            var send = formatData( data );
        }

        this.xmlHttp.send( send || null );

        return this;
    };
});

/**
 * Ajax makes a request using the method POST
 *
 * @param  String        url = The url which will be called
 * @param  Object       data = data will be sent
 * @param  Function callback = function to run when the server responds
 *
 * @return null
 */

TrueWizard.Ajax.Post = function( url, data, callback )
{
    this.Post.lastCall = new this( 'post', url + '?noCache=' + Math.round( Math.random() * 1000 ) )
        .setHeader('Content-Type', 'application/x-www-form-urlencoded')
        .request( data, callback );

    return null;
};

/**
 * Abort the last ajax request
 *
 * @return void
 */

TrueWizard.Ajax.Post.abort = function()
{
    if ( typeof this.lastCall == 'object' ) {
        this.lastCall.xmlHttp.abort();
    }
};