/**
 * Usa Prototype asi que se debe incluir previamente a incluir este script
 */
net = new Object();

net.READY_STATE_UNINITIALIZED = 0;
net.READY_STATE_LOADING       = 1;
net.READY_STATE_LOADED        = 2;
net.READY_STATE_INTERACTIVE   = 3;
net.READY_STATE_COMPLETE      = 4;

net.ContentLoader = Class.create();

net.ContentLoader.prototype = {

    /**
     * Funcion que inicializa los valores del objecto
     *
     * @param    object   component         Objecto que lo invoca
     * @param    string   url               URL del servidor a invocar
     * @param    string   method            POST o GET
     * @param    array    requestParams     Vector con los parametros
     * @param    array    options           Vector con opciones(errorHandler, successHandler, etc.)
     *
     * @access    public
     */
    initialize: function(component, url, method, requestParams, options) {
        this.component     = component;
        this.url           = url;
        this.method        = method;

        // Añadimos una variable ajaxenabled para que el servidor pueda
        // diferenciar cuando nos llegan los datos desde AJAX y cuando no
        requestParams.push('ajaxenabled=1');

        this.requestParams = requestParams;
        this.options       = options;
    },

    /**
     * Crea el objecto con el que nos vamos a comunicar con el servidor
     *
     * @access    public
     * @return    object        Devuelve el objeto creado
     */
    getTransport: function() {
        var xmlhttp;
        if (window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            try {
                xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch(e) {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
        } else if (window.createRequest) {
            xmlhttp = window.createRequest();
        }
        return xmlhttp;
    },

    /**
     * Se encarga de usar el objecto creado por getTransport para enviar los
     * parametros pasados como argumento. Se puede pasar cualquier numero de
     * de parametros.
     *
     * @access    public
     */
    sendRequest: function() {

        var requestParams = [];
        for (var i = 0; i < arguments.length; i++) {
            requestParams.push(arguments[i]);
        }
        var request = this.getTransport();
        request.open(this.method, this.url, true);
        request.setRequestHeader('Content-type','application/x-www-form-urlencoded');

        var oThis = this;
        request.onreadystatechange = function() {
            oThis.handleAjaxResponse(request);
        }
        request.send(this.queryString(requestParams));
    },

    /**
     * Convierte el vector de parametros a cadena en formato GET/POST que
     * se pasara al servidor mediante la conexion creada anteriormente.
     * Se le puede pasar cualquier numero de parametros
     *
     * @param    array    args  Vector con los parametros
     *
     * @access    private
     * @return    string        Cadena en formato POST/GET
     */
    queryString: function(args) {

        var requestParams = [];
        for (var i = 0; i < this.requestParams.length; i++) {
            requestParams.push(this.requestParams[i]);
        }
        for (var i = 0; i < args.length; i++) {
            requestParams.push(args[i]);
        }

        var queryString = "";
        if (requestParams && requestParams.length > 0) {
            queryString = requestParams[0];
            for (var i = 1; i < requestParams.length; i++) {
                queryString += '&'+requestParams[i];
            }
        }
        return queryString;
    },

    /**
     * Metodo al que se llama cuando se recibe la respuesta del servidor.
     * Si se ha definido los manejadores pasandoles dicha informacion al
     * constructor en el vector options, se llamaran a estos, sino se
     * llamara a los metodos definidos por defecto en esta clase.
     *
     * @param    object    request      Objecto respuesta
     *
     * @access    private
     */
    handleAjaxResponse: function(request) {
        if (request.readyState == net.READY_STATE_COMPLETE) {
            if (this.isSuccess(request)) {
                if (this.component.successHandler) {
                    this.component.successHandler(request);
                } else {
                    this.successHandler(request);
                }
            } else {
                if (this.component.errorHandler) {
                    this.component.errorHandler(request);
                } else {
                    this.errorHandler(request);
                }
            }
        }
    },

    /**
     * Devuelve si el estado HTTP es correcto o no
     *
     * @param    object    request      Objecto respuesta
     *
     * @access    private
     */
    isSuccess: function(request) {
        return request.status == 0 || (request.status >=200 && request.status < 300);
    },

    /**
     * Metodo al que se llama cuando todo ha ido bien
     *
     * @param    object    request      Objeto HTTP
     *
     * @access private
     */
    successHandler: function(request) {
        if (request.responseXML && request.responseXML.documentElement) {
            var xml = request.responseXML.documentElement;
            var msgs = xml.getElementsByTagName('messages');
            if (msgs.length) {
                var idmsg = msgs[0].getAttribute('to');
                if (idmsg && $(idmsg)) {
                    $(idmsg).innerHTML = '';
                }
            }
            var errors = xml.getElementsByTagName('errors');
            if (errors.length) {
                var iderror = errors[0].getAttribute('to');
                if (iderror && $(iderror) && (!idmsg || idmsg != iderror)) {
                    $(iderror).innerHTML = '';
                }
            }

            var html_msg = '';
            var msg = xml.getElementsByTagName('message');
            if (msg.length) {
                var html_msg = '<span class="gbox"><ul>';
                for (var i = 0; i< msg.length; i++) {
                    html_msg += '<li>'+msg[i].firstChild.data+'</li>';
                }
                html_msg += '</ul></span>';
            }

            var html_error = '';
            var error = xml.getElementsByTagName('error');
            if (error.length) {
                var html_error = '<span class="rbox">';
                for (var i = 0; i< error.length; i++) {
                    html_error += '<li>'+error[i].firstChild.data+'</li>';
                }
                html_error += '</span>';
            }
            if (iderror == idmsg) {
                if ($(iderror)) {
                    $(iderror).innerHTML = html_msg+html_error;
                }
            } else {
                if ($(idmsg)) {
                    $(idmsg).innerHTML = html_msg
                }
                if ($(iderror)) {
                    $(iderror).innerHTML = html_error;
                }
            }
        } else {
            if ($('log')) {
                $('log').innerHTML = '<span class="box">'+request.responseText+'</span>'
            } else {
                alert(request.responseText);
            }
        }
    },

    /**
     * Metodo al que se llama cuando ha habido algun error
     *
     * @param    object    request      Objeto HTTP
     *
     * @access private
     */
    errorHandler: function(request) {
        if ($('log')) {
            $('log').innerHTML = '<span class="rbox">'+request.responseText+'</span>';
        } else {
            alert(request.responseText);
        }
    }
}