(function ($) {
    $.fn.extend({SendForm: function (config) {
    	var setting = {
            fx: config.fx || false,
    		form: this,
            fields: {},
            id: this.attr('id') || Math.random(),
            action: config.action,
            validate: config.validate || function (fields, form, msg) { return true; },
            load: config.load || function (response, fields, form, msg) { return true; },
            wrap: null,
            wrapMessage: null,
            contentMessage: null,
            message: {
                ok: function (message) {
                    setting.contentMessage.html(message);
                    setting.wrapMessage.attr('class', setting.wrapMessage.attr('id')+'Ok')
                                       .slideDown('slow');
                },
                info: function (message) {
                    setting.contentMessage.html(message);
                    setting.wrapMessage.attr('class', setting.wrapMessage.attr('id')+'Info')
                                       .slideDown('slow');
                },
                error: function (message) {
                    setting.contentMessage.html(message);
                    setting.wrapMessage.attr('class', setting.wrapMessage.attr('id')+'Error')
                                       .slideDown('slow');
                },
                hide: function () {
                    setting.wrapMessage.slideUp('slow');
                }
            },
            send: false
    	};

        //  crea los elementos que reciben los mensajes
        setting.wrapMessage = $('<div id="'+ setting.id +'Message"></div>').css({width: this.width()});
        // fn de usuario que altera el elemento y retorna el que será afectado
        setting.contentMessage = ( ( config.wrapMessage ) ? config.wrapMessage( setting.wrapMessage ) : setting.wrapMessage ) || setting.wrapMessage;

        if (setting.fx==true) {
            // envoltura del formulario
            setting.wrap = $('<div id="'+ setting.id +'Wrap"></div>').css({height: this.height(), width: this.width(), overflow: 'hidden'});
            this.wrap( setting.wrap );

            setting.wrapMessage.insertBefore( '#'+ setting.wrap.attr('id') )
        } else {
            setting.wrapMessage.insertBefore( '#'+ this.attr('id') )
        }

        // itera config.fields y recupera desde form
        for (var f in config.fields ) {
        	setting.fields[config.fields[f]] = this.find('[name='+config.fields[f]+']');
        }

        // quita la acción submit
        this.find('form').bind('submit', function () { return false; });
        this.find('[name=submit]').bind('click', function () {
            // verifica que la configuración no pertenezca a un formulario que esta siendo enviado
            if (setting.send == false) {
                var data = setting.validate(setting.fields, setting.form, setting.message);
                if (data != false) {
                    // establece el estado de la configuración a enviando
                    setting.send = true;
                    if (setting.fx==true) { setting.form.fadeOut('slow'); }
                    jQuery.ajax( {
                        async: true,
                        contentType : 'application/x-www-form-urlencoded',
                        data: $.extend(data, {sendform : (new Date).getTime()}),
                        dataType: 'json',
                        timeout: 15000,
                        type: 'POST',
                        url: setting.action,
                        ifModified: false,
                        cache: false,
                        error: function (objXMLHttpRequest, error, exeption) {
                            if (setting.fx==true) {
                                setting.form.fadeIn('slow', function () {
                                    setting.load({error: true, message: 'Error inesperado'}, setting.fields, setting.form, setting.message);
                                });
                            } else {
                                setting.load({error: true, message: 'Error inesperado'}, setting.fields, setting.form, setting.message);
                            }
                            // devuelve el estado de la configuración a un estado que permite nuevos envíos
                            setting.send = false;
                        },
                        success: function (data, result) {
                            if (setting.fx==true) {
                                setting.form.fadeIn('slow', function () {
                                    setting.load(data.response, setting.fields, setting.form, setting.message);
                                });
                            } else {
                                setting.load(data.response, setting.fields, setting.form, setting.message);
                            }
                            // devuelve el estado de la configuración a un estado que permite nuevos envíos
                            setting.send = false;
                        }
                    });
                }
            }
        });
    }});
})(jQuery);
