function serializeForm(form, options) {
    var elements=Form.getElements(form);
    
    if (typeof options != 'object') options = { hash: !!options };
    else if (Object.isUndefined(options.hash)) options.hash = true;
    var key, value, submitted = false, submit = options.submit;
    
    var data = elements.inject({ }, function(result, element) {
        if (!element.disabled && element.name) {
            key = element.name; value = $(element).getValue();
            if (value != null && (element.type != 'submit' || (!submitted &&
                submit !== false && (!submit || key == submit) && (submitted = true)))) {
                if (key in result) {
                    if (!Object.isArray(result[key])) result[key] = [result[key]];
                    result[key].push(value);
                }
              else result[key] = value;
            }
        }
        return result;
    });
    
    return options.hash ? data : Object.toQueryString(data);
}

var formHandler= Class.create({
    form: null,
    identifier: null,
    updater: null,
    submitButton: null,
    submitText: null,
	requiredText: 'required',
    
    initialize: function(name,options) {
        if(typeof name=='object'){
            Element.extend(name);
            
            this.form=name;
        }else{
            this.form=$(name);
        }
        
		if( typeof(requiredText) != "undefined" ){
			this.requiredText=requiredText;
		}
		
        if( options ){
            //options=options.evalJSON();
        }
        
        options = Object.clone(options);
        
        this.options=options;
        
        var el, i = 0;
        while (el = this.form.elements[i++]){
            if( el.name=='submit' && el.type!='submit' ){
                alert('error: form has field called submit which is not a submit button');
                continue;
            }else if( el.name=='action' ){
                alert('error: form has field called action');
                continue;
            }else if( el.name=='target' ){
                alert('error: form has field called target');
                continue;
            }else if( el.name=='reset' ){
                alert('error: form has field called reset');
                continue;
            }
            //alert(el.type);
            if( el.type != 'hidden' && el.type!='submit' && el.type!='button' && el.type!='image' && el.type!=undefined && el.type!='fieldset' ){
                //el.observe('change', reset_field.bindAsEventListener(el)); //doesn't work in ie!
                new Form.Element.EventObserver(el, this.reset_field.bindAsEventListener(el));
            }else if( el.type=='submit' || el.type=='image' ){
                this.submitButton=el;
            }
        }
        
        this.form.observe('submit', this.onSubmit.bindAsEventListener(this));

        if (this.form.select('input[name="UPLOAD_IDENTIFIER"]')[0]) {
            this.identifier = this.form.select('input[name="UPLOAD_IDENTIFIER"]')[0].value;
        
            var iframe = document.createElement('iframe');
            iframe.setAttribute('id', 'upload');
            iframe.setAttribute('name', 'upload'); 
            iframe.id='upload'; //IE
            iframe.name='upload'; //IE
            iframe.setAttribute('style', 'display: none; width: 0; height: 0;');
            iframe.setAttribute('src', 'about:blank');
            iframe.style.display='none'; //IE
            iframe.style.width='0'; //IE
            iframe.style.height='0'; //IE
            
            this.form.appendChild(iframe);
            
            
            //alert($('upload'));
            //alert($('upload').name);
            
            //alert(this.form.targer);
            
            if( self.frames['upload'] ){
                if(self.frames['upload'].name != 'upload') {
                    self.frames['upload'].name = 'upload';
                }
            }
            
            this.form.target='upload';
        }
    },
    
    reset_field: function(e)
    {
        //this.style.backgroundColor='#FFFFFF';
    },
    
    onSubmit: function(evt)
    {
        if( evt ){
            Event.stop(evt);
        }
        
        if( this.submitButton ){
            submitText=this.submitButton.innerHTML;
        
            this.submitButton.disabled=true;
            this.submitButton.innerHTML='Saving...';
        }
    
        var url = location.href;
        
        var pars = serializeForm(this.form);
            pars=pars+'&validate=1';
            
    
        $$('div.error').each(function(name, index) {
            name.parentNode.removeChild(name);
        });
        
        var myAjax = new Ajax.Request(
                url, 
                {
                    method: 'post', 
                    parameters: pars, 
                    onComplete: this.submitResponse.bindAsEventListener(this)
        });
        
        if( typeof(Ext)!=='undefined' ){
            Ext.MessageBox.show({                
                msg: 'Saving your data, please wait...',
                progressText: 'Saving...',
                width:300,
                wait:true,
                waitConfig: {interval:200},
                animEl: 'mb7'
            });
        }
                
        return false;    
    },
    
    submitResponse: function(originalRequest)
    {
        
        options = this.options;

        if( options.errorMethod==undefined ){
            options.errorMethod='inline'
        }
        
        result = originalRequest.responseText;
        debug(result);
        
        try {
            returned=result.evalJSON();
        } catch(ex) {
            alert(result);
        }
    
        if( this.submitButton ){
            this.submitButton.disabled=false;
            this.submitButton.innerHTML=submitText;
        }
    
        if( parseInt(returned)!=returned-0 ){
            if( typeof(Ext)!=='undefined' ){
                Ext.MessageBox.hide();
            }
            
            if( returned.length>0 ){
                var errors='';
                
                for( i=0;i<returned.length;i++ ){
                    var pos=returned[i].indexOf(' ');
                    
                    if( pos==-1 ){
                        var field=returned[i];
                        var error=this.requiredText;
                    }else{
                        var field=returned[i].substring(0,pos);
                        var error=returned[i].substring(pos+1);
                    }
                    
                    var parent='';
                    
                    if( this.form[field] ){
                        if( this.form[field].style ){
                            if( !firstError ){
                                var firstError=field;
                            }
                            
                            parent=this.form[field].parentNode;
                        }else if( this.form[field][0] ){
                            parent=this.form[field][0].parentNode.parentNode;
                        }
                        errors+=field+'\n';
                    }else if( this.form[field+'[]'] ){
                        if( this.form[field+'[]'].style ){
                            if( !firstError ){
                                var firstError=field;
                            }
                            
                            parent=this.form[field+'[]'].parentNode;
                        }else if( this.form[field+'[]'][0] ){
                            
                            parent=this.form[field+'[]'][0].parentNode.parentNode;
                        }
                        
                        errors+=field+'\n';
                    }else{
                        errors+=error+'\n';
                    }
                                            
                    if( parent && options.errorMethod=='inline' ){
                        div = document.createElement("div");
                        div.innerHTML=error;
                        div.style.color='red';
                        div.className='error';
                        
                        parent.appendChild(div);
                    }
                }
                
                if( options.errorMethod=='alert' ){
                    alert('Please check the required fields\n'+errors);
                }
				
				var tab, node;
				
				node=this.form[firstError];
				
				while( node=node.parentNode ){					
					if( node.style.display=='none' ){
						tab=node.id;
						break;
					}
					
					if( node.nodeName=='BODY' ){
						break;
					}
				}
				
				if( tab && set_tab ){
					debug('switch tab: '+tab);
					
					set_tab(tab);					
				}
				
                this.form[firstError].focus();

				if( Recaptcha ){
					Recaptcha.reload();
				}
            }
        }else{
            if( this.identifier ){
                this.onCreate();
            }
            
            window.onbeforeunload = null;
            
            this.form.submit();
        }
    },

    onCreate: function() {
        $('upload').observe('load', this.onComplete.bindAsEventListener(this));
        
        if( typeof(Ext)!=='undefined' ){
            Ext.MessageBox.show({
                title: 'Please wait - Uploading',
                msg: 'Uploading..',
                progressText: 'Initializing...',
                width:400,
                progress:true,
                closable:false
            });
            updater = new PeriodicalExecuter(this.__tick.bind(this), 1);
        }
    },

    // Timer function
    __tick: function(identifier) {
        new Ajax.Request('/_lib/ajax/upload_progress.php', { 
            method: 'post', 
            parameters: { 'uniq': this.identifier }, 
            onComplete: function(result){
               // console.log(result.responseText);
                var data=eval('('+result.responseText+')');
                //alert(data);
                if( data.perc ){
                    Ext.MessageBox.updateProgress((data.perc/100), data.perc+'% completed');
                    Ext.MessageBox.updateText(data.status);
                }else{
                    /*
                    this.failCount++;
                    
                    if( this.failCount == 10 ){
                        Ext.MessageBox.hide();
                        //updater.stop();
                        //window.stop();
                        //document.execCommand('Stop')
                        alert('Upload has stopped. Please check file size.');
                        window.location.href=window.location.href
                    }
                    */
                }
            }
        });
    },

    onComplete: function() {
        updater.stop();
        window.location.href=this.form.select('input[name="redirect"]')[0].value
    }
});

