
var FormValidator=Class.create({
    form: null,                 //Form objektum
    options: {},                //Beállítások
    displayedFields: $H({}),        //Az előző lekérdezéskor érintett mezőket tároljuk itt, hogy a következő hívásra le tudjuk törölni
    saving: false,              //Tart-e a mentés
    data: {},

    STATUS_ERROR: 0,
    STATUS_SUCCESS: 1,

    GLOBALFIELD: '_global',

    initialize: function(form,options) {
        this.form=$(form);
        var o={
            messageHTML: {},
            messageErrorClass: 'error',
            messageSuccessClass: 'success',
            defaultErrorMessage: 'Rendszerhiba! Kérjük próbálkozzon később.',

            url: (this.form ? this.form.action : ''),
            method: (this.form ? this.form.method : 'post'),   //'get','post'
            extraParams: {},

            onBeforeSave: null,
            onPrepareData: null,
            
            //Ajax state
            onSuccess: null,
            onFailed: null,
            onComplete: null,

            onDisplayMessage: null, //(field,message,status)
            onClearMessage : null
        };
        this.options=Object.extend(o,options);
        if (this.form) this.form.observe('submit', function(e) {Event.stop(e);this.save();return true;}.bind(this));
    },

    getForm: function() {return this.form;},
    getOption: function(name) {return this.options[name];},
    trigger: function(functionname,param1,param2,param3) {
        if (this.getOption(functionname) && this.getOption(functionname)(param1,param2,param3)==false) return true;
        return false;
    },

    displayMessage: function(field,messages,status) {
        this.displayedFields.set(field,1);
        messages=$A(messages);
        //onDisplayMessage van-e megadva? Ha igen és false-al tér vissza, akkor nem folytatjuk a kiírást
        if (this.trigger('onDisplayMessage',field,messages,status)) return;

        var classname= this.getOption( status==this.STATUS_ERROR ? 'messageErrorClass' : 'messageSuccessClass');
        $H(this.getOption('messageHTML')).each(function(pair) {
            var element=$(pair.key.replace("{field}",field));
            
            if (element) {
                //előállítjuk az üzenet vázát, ezután csak magát az üzit kell belecserélni
                var _msg=pair.value.replace('{field}',field).replace('{class}',classname);
                messages.each(function(value) {
                    var msg=_msg.replace('{message}',value);
                    element.insert(msg);
                });
            }
        });
    },

    clearMessages: function() {
        this.displayedFields.each((function(pair) {
            this.clearMessage(pair.key);
        }).bind(this));
    },

    clearMessage: function(field) {
        if (this.getOption('onClearMessage') && this.getOption('onClearMessage')(field)==false) return;

        $H(this.getOption('messageHTML')).each(function(pair) {
            var element=$(pair.key.replace("{field}",field));
            if (element) element.update();
        });
        this.displayedFields.unset(field);
    },

    getDefaultErrorResult: function() {
        return {status: this.STATUS_ERROR,
                 errorMessages: {'_global' : [this.getOption('defaultErrorMessage')]}
                };
    },

    save : function() {
        this.saving=true;
        this.clearMessages();
        if (this.trigger('onBeforeSave', this)) return;
        
        var params = (this.form ? this.form.serialize(true) : {});
        if (this.getOption('onPrepareData')) {
            params=this.getOption('onPrepareData')(params);
        }
        
        new Ajax.Request( this.getOption('url'), {
            method: this.getOption('method'),
            parameters: params,
            onSuccess: (function(res) {
                var ret = res.responseJSON;
                this.data = (ret) ? ret : this.getDefaultErrorResult();
                if (this.trigger('onSuccess', this)) return;    //Ha van user által megadott onSuccess függvény, akkor azt hívjuk meg először
                this.evaluateResult();
            }).bind(this),
            onFailure: (function() {
                this.data=this.getDefaultErrorResult();
                if (this.trigger('onFailed', this)) return;    //Ha van user által megadott onSuccess függvény, akkor azt hívjuk meg először
                this.evaluateResult();
            }).bind(this),
            onComplete: (function() {
                this.saving=false;
                this.trigger('onComplete', this);
            }).bind(this)
        });
    },

    //Kiértékeljük a szervertől kapott választ
    evaluateResult: function() {
        //Hibaüzik kiírása
        data=$H(this.data);
        var messages=$H(data.get('error_messages'));
        if (messages) {
            messages.each((function(pair) {
               this.displayMessage(pair.key, pair.value, this.STATUS_ERROR);
            }).bind(this));
        }

        //Success üzenetek kiírása
        messages=$H(data.get('success_messages'));
        if (messages) {
            messages.each((function(pair) {
               this.displayMessage(pair.key, pair.value, this.STATUS_SUCCESS);
            }).bind(this));
        }

        //commands
        var commands=$H(data.get('commands'));
        if (commands) {
            commands.each(function(pair) {
                switch (pair.key) {
                      case 'set':
                          //Beállítjuk a kapott kulcs/érték párokat
                          $H(pair.value).each(function(data) {
                              $(data.key).value=data.value;
                          })
                          break;
                      case 'update':
                          $H(pair.value).each(function(data) {
                              $(data.key).innerHTML(data.value);
                          })
                          break;
                      case 'alert':
                          $H(pair.value).each(function(data) {
                              window.alert(data.value);
                          })
                          break;
                      case 'reload':
                          window.location.reload();
                          break;
                }
            })
        }
        
        //url
        var url=data.get('url');
        if (url) document.location.href=url;
    },

    //Eredmények kikérdezésére használható függvények

    getStatus: function() {
        if (this.data.status!=undefined && this.data.status==this.STATUS_SUCCESS) return this.STATUS_SUCCESS;
        return this.STATUS_ERROR;
    },

    getParams: function() {
        return this.data.params || {};
    },

    getParam: function(param,def) {
        return this.getParams().param || def;
    },

    getErrorMessages: function() {
        return this.data.errorMessages || {};
    },

    getErrorMessage: function(field,def) {
        return this.getErrorMessages()[field] || def || '';
    },

    getSuccessMessages: function() {
        return this.data.successMessages || {};
    },

    getSuccessMessage: function(field,def) {
        return this.getSuccessMessages()[field] || def || '';
    },

    getUrl: function(def) {
        return this.data.url || def || '';
    },

    getResult: function() {
        return this.data;
    }
});
