var JsonRPCForm = Class.create({
    initialize: function(form, options) {
        this.options = Object.extend({
            method: 'post',
            onSuccess: function() {},
            onFailure: function() {},
            onErrors: function() {},
            msgLoading: 'Saving...',
            msgError: 'An unexpected error occurred. Please try again.',
            msgFailure: 'Failed!',
            msgComplete: 'Complete.'
        },
        options || {});
        this.form = $(form);
        if (!this.form) {
            return null;
        }
        this.form._RPC_HANDLER_ = this;
        if (!this.form.progress) {
            if (this.form.down('.progress')) {
                this.form.progress = this.form.down('.progress');
            } else {
                this.form.progress = undefined;
            }
        }
        this.form.observe(
        'submit',
        function(evt) {
            if (evt.stopped) return false;
            evt.stop();
            var form = evt.element();
            var rpc_handler = form._RPC_HANDLER_;
            var action = '/rpc' + form.action.parseUri().path;
            var params = form.serialize(true);
            new Ajax.Request(
            action,
            {
                method: rpc_handler.options.method,
                parameters: params,
                onLoading: function(transport) {
                    if (form.progress) {
                        form.progress.innerHTML = rpc_handler.options.msgLoading;
                    }
                    rpc_handler._clearErrors();
                },
                onFailure: function(transport) {
                    if (form.progress) {
                        form.progress.innerHTML = rpc_handler.options.msgError;
                    }
                    rpc_handler._handleErrors([{
                        key: '_BOOM_',
                        text: rpc_handler.options.msgError
                    }]);
                    rpc_handler.options.onFailure();
                },
                onComplete: function(transport) {
                    var result = transport.responseText.evalJSON()[0];
                    if (result.error && result.error.data.messages.length) {
                        // error condition
                        rpc_handler._handleErrors(result.error.data.messages);
                        rpc_handler.options.onErrors(result);
                    } else {
                        // success condition
                        if (form.progress) {
                            form.progress.innerHTML = rpc_handler.options.msgComplete;
                        }
                        rpc_handler.options.onSuccess(result);
                    }
                }
            }
            );
        }
        );
    },
    _clearErrors: function() {
        var form = this.form;
        if (form.__MM) {
            form.__MM.hideAllMessages();
        }
    },
    _handleErrors: function(a_mes) {
        var form = this.form;
        if (form.progress) {
            form.progress.innerHTML = this.options.msgError;
        }
        if (!form.__MM) {
            this.form.__MM = new MessageManager({
                'form': form.id,
                'messages': []
            });
        }
        a_mes.each(function(m) {
            var k = m.key.split(/\./);
            var args = {
                'validation': k[0],
                'field': k[1] || generateGuid(),
                'text': m.text
            };
            if (k[2]) args['form'] = k[2];
            form.__MM.addShowMessage(args);
        });
    }
});

