if (!window.ControlForm) {

    window.ControlForm = function(form, callback) {
        var type = typeof(callback);
        this.hasBeenSearched = false;

        if (form == null) {
            throw "ControlForm: 'form' é NULL!";
        }

        this.formActual = new Array();
        this.formChanged = new Array();
        this.ignoredFields = {};
        this.active = true;
        this.form = form;
        this.listener = function() {
            this.setFormChanged();
        }.bind(this);
        this.callback = (type.toLowerCase() == "string")
        	? function() {$(callback).style.display = "";}
        	: function() {callback();};

        ControlForm.put(this);
    };

    ControlForm.prototype = {
        search: function() {
            this.hasBeenSearched = true;
        },
        
        initFormActual: function() {
            for (var i = 0; i < this.form.elements.length; i++) {
                var element = this.form.elements[i];

                if (element.type != null && String.isNotEmpty(element.name) && this.ignoredFields[element.name] == null) {
                    switch (element.type.toLowerCase()) {
                    case "text":
                    case "hidden":
                    case "textarea":
                        this.formActual[i] = element.value;
                        break;
                    case "checkbox":
                        if (element.checked) this.formActual[i] = element.value;
                        break;
                    case "radio":
                        this.formActual[i] = (element.value + element.checked);
                        break;
                    case "select":
                        this.formActual[i] = element.selectedIndex;
                        break;
                    case "select-one":
                        this.formActual[i] = element.selectedIndex;
                        break;
                    }
                }
            }
        },

        addIgnoredField: function(name) {
            if (name != null && typeof(name).toLowerCase() == "string") this.ignoredFields[name] = name;
        },

        setFormChanged: function() {
            var changed = false;

            for (var i = 0; i < this.form.elements.length; i++) {
                var element = this.form.elements[i];

                if (element.type != null && String.isNotEmpty(element.name) && this.ignoredFields[element.name] == null) {
                    switch (element.type.toLowerCase()) {
                    case "text":
                    case "hidden":
                    case "textarea":
                        this.formChanged[i] = element.value;
                        break;
                    case "checkbox":
                        if (element.checked) this.formChanged[i] = element.value;
                        break;
                    case "radio":
                        this.formChanged[i] = (element.value + element.checked);
                        break;
                    case "select":
                        this.formChanged[i] = element.selectedIndex;
                        break;
                    case "select-one":
                        this.formChanged[i] = element.selectedIndex;
                        break;
                    }
                }
            }

            for (var i = 0; i < this.formActual.length; i++) {
                if (this.formChanged[i] != this.formActual[i]) {
                    changed = true;
                    break;
                }
            }

            if (changed && this.hasBeenSearched) this.callback();
            return changed;
        },

        registerEvent: function(element, name) {
            if (element.addEventListener) {
                element.addEventListener(name, this.listener, false);
            } else {
                var b = element.attachEvent("on" + name, this.listener);
            }
        },

        deregisterEvent: function(element, name) {
            if (element.removeEventListener) {
                element.removeEventListener(name, this.listener, false);
            } else {
                element.detachEvent("on" + name, this.listener);
            }
        },

        resetFields: function() {
            for (var i = 0; i < this.form.elements.length; i++) {
                var element = this.form.elements[i];

                if (element.type != null && this.ignoredFields[element.name] == null) {
                    switch (element.type.toLowerCase()) {
                    case "text":
                    case "textarea":
                        element.value = "";
                        break;
                    case "radio":
                    case "checkbox":
                        element.checked = false;
                        break;
                    case "select":
                        element.selectedIndex = 0;
						break;
                    case "select-one":
                        element.selectedIndex = 0;
						break;
                    }
                }
            }
            this.setFormChanged();
        },

        setActive: function(active) {
            this.active = active;
        },

        initialize: function() {
            if (this.initialized) return;
            if (!this.active) return;

            for (var i = 0; i < this.form.elements.length; i++) {
                var element = this.form.elements[i];

                if (element.type != null && String.isNotEmpty(element.name) && this.ignoredFields[element.name] == null) {
                    switch (element.type.toLowerCase()) {
                    case "text":
                        this.registerEvent(element, "blur");
                        break;
                    case "radio":
                    case "checkbox":
                        this.registerEvent(element, "click");
                        break;
                    case "select":
                    case "textarea":
                    case "hidden":
                        this.registerEvent(element, "change");
                        break;    
                    case "select-one":
                        this.registerEvent(element, "change");
                        break;
                    }
                }
            }

            this.initFormActual();
            this.initialized = true;
        },

        destroy: function() {
            for (var i = 0; i < this.form.elements.length; i++) {
                var element = this.form.elements[i];

                if (element.type != null) {
                    switch (element.type.toLowerCase()) {
                    case "text":
                        this.deregisterEvent(element, "blur");
                        break;
                    case "radio":
                    case "checkbox":
                        this.deregisterEvent(element, "click");
                        break;
                    case "select":
                    case "textarea":
                    case "hidden":
                       this.deregisterEvent(element, "change");
                        break;
                    case "select-one":
                        this.deregisterEvent(element, "change");
                        break;
                    }
                }
            }

            this.formActual = null;
            this.formChanged = null;
            this.ignoredFields = null;
            this.form = null;
            this.listener = null;
            this.callback = null;
        }
    };

    ControlForm.resetForm = function(form, options){
    	options = Object.extend({
    		executeBlurAfterText:false,
    		hiddenNames:[]
    	}, options || {});
    	options.hiddenNames = $A(options.hiddenNames);
    	
    	$A($(form).elements).each(function(elem){
        	elem = $(elem);

        	if(elem.tagName.toLowerCase() == "select"){
        		elem.selectedIndex = 0;
        	}else{
            	switch(elem.type.toLowerCase()){
            	case "text":
            		elem.value = "";
            		if(options.executeBlurAfterText){
            			Consulte.runEvent(elem, "blur");
            		}
            		break;
            	case "hidden":
            		if(options.hiddenNames.include(elem.name)){
            			elem.value = "";
            		}
            		break;
            	}
        	}
        });
    };

    ControlForm._controlsByName = {};
    ControlForm.get = function(formName) {
        if (formName != null) {
            return this._controlsByName[formName];
        }
        return null;
    };
    ControlForm.put = function(control) {
        if (control != null) {
        	try{
        		this._controlsByName[control.form.name] = control;
        	}catch(e){/* Form sem nome é ignorado */}
        }
    };
    ControlForm.remove = function(control) {
        if (control != null) {
            control.destroy();
            try{
            	delete this._controlsByName[control.form.name];
            }catch(e){/* Form sem nome é ignorado */}
        }
    };
    ControlForm.removeAll = function() {
        var aux = Object.extend({}, this._controlsByName);
        for (var name in aux) {
            this.remove(aux[name]);
        }
    };

    if (window.attachEvent) {
        window.attachEvent("onunload", function() {
            ControlForm.removeAll();
        });
    }
}