/**
 *  Clase para manejar formularios
 *
 *  @require    prototype.js
 */
FormsHandler = Class.create();

FormsHandler.prototype = {

    /**
     * Inicializamos la clase
     *
     * @param   string  idform          ID del formulario a tratar
     * @param   ref     onsubmitfunc    Referencia a la funcion a llamar
     *
     * @access  public
     */
    initialize: function(idform, onsubmitfunc) {
        this.form = $(idform);
        if (this.form) {
            this.form.onsubmit = onsubmitfunc;
        }
    },

    /**
     * Obtenemos vector con los resultados del POST
     *
     * @access  public
     */
    genArgs: function() {
        if (this.form) {
            this.params = [];
            for (var i = 0; i < this.form.length; i++) {
                this.getValue(this.form[i]);
            }
        }
    },

    /**
     * Devuelve el vector de parametros generado por genArgs, si no se ha
     * generado se llama automaticamente a dicha funcion
     *
     * @access  public
     */
    getArgs: function() {
        this.genArgs();
        return this.params;
    },

    /**
     * A�ade los valores asociados a cada campo del formulario
     * teniendo en cuenta el tipo, si es multiple o no, etc.
     *
     * @param   object  elem    DOM Input Element
     *
     * @access  public
     */
    getValue: function(elem) {
        switch (elem.type) {
            case 'text':
            case 'hidden':
            case 'submit':
            case 'file':
                this.params.push({'key' : elem.name, 'value' : elem.value});
                break;
            case 'select-one':
                this.params.push({'key' : elem.name, 'value' : elem.options[elem.selectedIndex].value});
                break;
            case 'select-multiple':
                var i = 0;
                for (i = 0; i < elem.options.length; i++) {
                    if (elem.options[i].selected) {
                        this.params.push({'key' : elem.name, 'value' : elem.options[i].value});
                    }
                }
                break;
            case 'radio':
            case 'checkbox':
                if (elem.checked) {
                    this.params.push({'key' : elem.name, 'value' : elem.value});
                }
                break;
            default: alert('tipo de elemento no implementado ['+elem.type+']');
        }
    },

    /**
     * Convierte el vector de parametros a cadena en formato GET/POST que
     * se pasara al servidor mediante la conexion creada anteriormente. Se
     * puede pasar cualquier numero de parametros. Si no se ha encontrado
     * ningun valor del formulario se llama automaticamente al metodo
     * genArgs.
     *
     * @access  public
     * @return  array           Vector en formato POST/GET
     */
    queryParams: function() {

        this.genArgs();

        var requestParams = [];
        if (this.params) {
            for (var i = 0; i < this.params.length; i++) {
                requestParams.push(this.params[i].key+'='+encodeURIComponent(this.params[i].value));
            }
        }
        if (arguments.length) {
            for (var j = 0; j < args.length; j++) {
                requestParams.push(args[j].key+'='+encodeURIComponent(args[j].value));
            }
        }
        return requestParams;
    },

    /**
     * Detectara si algun valor del formulario ha cambiado o no, de forma
     * que se pueda mostrar un mensaje del tipo "Ha cambiado alguno de sus
     * datos, quiere descartarlos?"
     *
     * @access  public
     */
    hasChanged: function() {
        if (this.form) {
            for (var i = 0; i < this.form.length; i++) {
                if (this.hasChangedElement(this.form[i])) {
                    return true;
                }
            }
        }
        return false;
    },

    /**
     * Detecta si un campo del formulario ha cambiado basandose en el tipo
     *
     * @param   object  elem    DOM Input Element
     *
     * @access  public
     * @return  bool
     */
    hasChangedElement: function(elem) {
        switch (elem.type) {
            case 'text':
            case 'hidden':
            case 'submit':
            case 'file':
                return (elem.value != elem.defaultValue);
            case 'select-one':
            case 'select-multiple':
                var i = 0;
                for (i = 0; i < elem.options.length; i++) {
                    if (elem.options[i].selected != elem.options[i].defaultSelected) {
                        return true;
                    }
                }
                return false;
            case 'radio':
            case 'checkbox':
                return (elem.checked != elem.defaultChecked || elem.value != elem.defaultValue);
            default: alert('tipo de elemento no implementado ['+elem.type+']');
        }
    }
}

/**
 *  Para trabajar con selects anidados usando AJAX
 *
 *  @require    prototype.js
 *  @require    c_net.js
 */
FormsHandler.DoubleCombo = Class.create();

FormsHandler.DoubleCombo.prototype = {

    /**
     *  Inicializamos la clase
     *
     *  @param   string  masterid        ID del select maestro
     *  @param   mixed   slaveid         ID del select esclavo
     *  @param   string  url             URL de la que obtener los datos
     *  @param   array   options         Opciones a pasar con el POST
     *
     *  @access  public
     */
    initialize: function(masterid, slaveid, url, options) {
        this.master = document.getElementById(masterid);
        if (!this.master) {
            alert('Master '+masterid+' not detected!');
        }
        if (typeof(slaveid) == 'object') {
            this.slaveobj = slaveid;
            this.slave    = document.getElementById(slaveid.master.id);
        } else {
            this.slave = document.getElementById(slaveid);
        }
        if (!this.slave) {
            alert('Slave '+slaveid+' not detected!');
        }
        options.Parameters.push('e='+this.slave.id);

        this.options    = options;
        if (options && options.Parameters) {
            var requestParameters = options.Parameters;
        } else {
            var requestParameters = [];
        }

        this.netHandler = new net.ContentLoader(this, url, 'POST', requestParameters, options);

        this.initializeBehavior();
    },

    /**
     *  Inicializamos el comportamiento
     */
    initializeBehavior: function() {
        var oThis = this;
        this.master.onchange = function() { oThis.masterComboChanged(); };
    },

    /**
     *  Listener que se dispara cuando el select maestro ha cambiado
     */
    masterComboChanged: function() {
        var q = this.master.options[this.master.selectedIndex].value;

        if (this.options.params_to_add) {
            var i     = 0;
            var value = '';
            for (i = 0; i < this.options.params_to_add.length; i++) {
                var obj = $(this.options.params_to_add[i]);
                if (obj.type == 'select-one') {
                    value = obj.options[obj.selectedIndex].value;
                } else {
                    value = obj.value;
                }
                this.options.Parameters.push(escape(this.options.params_to_add[i])+'='+escape(value));
            }
        }
        this.netHandler.sendRequest(this.master.id+'='+q);
    },

    /**
     *  Funcion que crea las opciones que iran en el select
     */
    createOptions: function(ajaxResponse) {
        var newOptions = [];
        if (this.options && this.options.add_empty_opt) {
            var text = (this.options && this.options.add_empty_label) ? this.options.add_empty_label : '';
            newOptions.push(new Option(text, ''));
        }
        var entries = ajaxResponse.getElementsByTagName('option');
        for (var i = 0; i < entries.length; i++) {
            var text  = this.getElementContent(entries[i], 'text');
            var value = this.getElementContent(entries[i], 'value');
            newOptions.push(new Option(text, value));
        }
        return newOptions;
    },

    /**
     *  Devuelve el contenido de la porcion de XML de un <option>
     */
    getElementContent: function(elem, tag) {
        var child = elem.getElementsByTagName(tag)[0];
        if (child.text != undefined) {
            return child.text;
        }
        return child.textContent;
    },

    /**
     *  Se llamara cuando se reciba la respuesta del servidor
     */
    successHandler: function(request) {
        if (!request.responseXML) {
            return false;
        }
        var errors = request.responseXML.documentElement.getElementsByTagName('error');
        if (errors.length > 0) {
            this.errorHandler(request.responseXML.documentElement);
            return false;
        }
        var slaveOptions  = this.createOptions(request.responseXML.documentElement);
        this.slave.length = 0;

        /*if (slaveOptions.length > 0) {
            this.slave.add(new Option('', ''), null);
        }*/
        for (var i = 0; i < slaveOptions.length; i++) {
            try {
                this.slave.add(slaveOptions[i], null);
            } catch (e) {
                this.slave.add(slaveOptions[i], -1);
            }
        }

        if (this.slaveobj && this.slaveobj.masterComboChanged) {
            var oThis = this.slaveobj;
            oThis.masterComboChanged();
        }
    },

    /**
     *  Si se ha especificado una funcion para manejar los errores la llamamos
     */
    errorHandler: function(request) {
        if (this.options.errorHandler) {
            this.options.errorHandler(request);
        } else {
            alert('ERROR: '+request);
        }
    }
}
