// optional dependency on $.enhance() and $().enhance()

(function($){
    $.AjaxSubmit = {
        escape: function(myid) {
            return myid.replace(/:/g,"\\:").replace(/\./g,"\\.");
        },
        htmlBodyFilter: function(text, type){
            var p = text.indexOf('<body');
            if (p < 0) return text;
            var e = text.lastIndexOf('</body');
            return '<div' + text.substring(p + 5, e) + '</div>';
        },
        replaceForm: function(form, newForm, replace) {
            if (replace) {
                var replaceWith = newForm.find('#' + $.AjaxSubmit.escape(replace.attr('id')));
                if (replaceWith.length) {
                    var viewState = newForm.find('input[name=javax.faces.ViewState]').val();
                    if (viewState) {
                        form.find('input[name=javax.faces.ViewState]').val(viewState);
                    }
                    replace.replaceWith(replaceWith);
                    return;
                }
            }
            form.hide();
            newForm.hide();
            form.replaceWith(newForm);
            newForm.show();
        },
        submit: function(action, replace) {
            var form = action.parents('form');
            if (!form.length) return true;
            var name = action.attr('name');
            return this.submit0(form, name, replace);
        },

        submit1: function(e) {
            if (e.result === false) return false;
            var name = $(e.target).attr('name');
            var form = $(this);
            var result;
            if (form.attr('enctype') == "multipart/form-data") {
                result = $.AjaxSubmit.upload(form);
            } else {
                result = $.AjaxSubmit.submit0(form, name, e.data);
            }
            if (!result) {
                e.preventDefault();
                e.stopPropagation();
            }
            return result;
        },

        submit0: function(form, name, replace) {
            var data = form.serializeArray();
            data.push({name: name, value: ''});

            var options = {
                form: form,
                url: form.attr('action'),
                type: 'POST',
                dataType: 'html',
                global: false,
                data: data,
                success: function(html) {
                    html = $.AjaxSubmit.htmlBodyFilter(html, "html");
                    var formId = this.form.attr('id');
                    var selector = '#' + $.AjaxSubmit.escape(formId);
                    var newForm;
                    if ($.isFunction($.enhance)) {
                        newForm = $.enhance(html, selector);
                    } else {
                        newForm = $(html, selector);
                    }
                    $.AjaxSubmit.replaceForm(this.form, newForm, replace);
                },
                error: function(m, s) {
                    alert(m.statusText);
                    // TODO
                }
            };
            $.ajax(options);
            return false;
        },
        upload: function(form) {
            if (!form || !form.length) return false;
//    console.log(form.find(':file').value());
            var iframe = form.parents('body').find('#uploadIframe');
            if (!iframe.length) {
                form.after('<iframe name="uploadIframe" id="uploadIframe" src="about:blank" style="display: none"/>');
                iframe = form.parents('body').find('#uploadIframe');
            }
            iframe[0].formId = form.attr('id');
            form.attr("enctype", "multipart/form-data");
            form.attr('target','uploadIframe');
            var timeout = 3000;
            var i = setInterval(function(){
                if (iframe[0].formHtml) {
                    form.html(iframe[0].formHtml);
                    if ($.isFunction(form.enhance)) form.enhance();
                    clearInterval(i);
                } else if (timeout-- == 0) {
                    clearInterval(i); // TODO message
                }
            }, 100);
            return true;
        }
    };
    $.fn.ajaxSubmit = function(e) {
        return $.AjaxSubmit.submit1.call(this.get(0), e);
    };
    $.fn.makeAjaxSubmit = function() {
        this.bind('submit', $.AjaxSubmit.submit1);
    };
})(jQuery);