FormValidator = Class.create();
FormValidator.prototype = {
    initialize: function(id, options) {
        this.id = id;
        this.form = $(this.id);
        this.elements = this.form.elements;
        this.labels = $A(this.form.getElementsByTagName('label'));
        this.submitCallback = options.submitCallback;
        this.form.validator = this;
        this.form.onsubmit = this.validate;
    },

    addRule: function(name, options) {
        if (typeof name == 'object') {
            elt = name;
        } else {
            var elt = this.getElement(name);
        }

        if (!elt) return false;

        this.bindLabel(elt);
        elt.showError = this.showError;
        elt.hideError = this.hideError;
        elt.highlightError = this.highlightError;
        elt.required = (options.required) ? true : false;
        elt.valid = true;

        var callback = options.callback;
        if (typeof callback == 'function') {
            elt.callback = callback;
            Event.observe(elt, 'change', this.validateElementCallback);
            Event.observe(elt, 'keyup', this.validateElementCallback);
            Event.observe(elt, 'blur', this.validateElementCallback);
        }
    },

    validate: function() {
        var result = $A(this.elements).collect( function(elt) {
            if (!elt.showError) return true;
            var result = elt.form.validator.validateElement(elt);
            if (!result) {
                elt.highlightError(elt);
            }
            return result;
        });

        result = $A(result).all();

        if (!result)
            return false;

        if (this.validator.submitCallback)
            return this.validator.submitCallback.apply(null, [this]);
        else
            this.submit();
    },

    validateElement: function(elt) {
        if (!elt.showError)
            return true;

        elt.hideError(elt);
                
        if (elt.value == '' || elt.className == 'hint') {
            if (elt.required) {
                elt.showError(elt, 'cannot be empty');
                return false;
            } else {
                return true;
            }
        }

        if (!elt.callback)
            return true;

        var result = elt.callback.apply(null, [elt]);

        if (typeof result == 'boolean' && result == true) {
            elt.hideError(elt);
            return true;
        } else {
            elt.showError(elt, result);
            return false;
        }
    },

    validateElementCallback: function(event) {
    	var node = (this.tagName == 'INPUT') ? this : event.srcElement;
        node.form.validator.validateElement(node);
    },

    bindLabel: function(elt) {
        elt.label = this.labels.find( function(label) {
            return (label.htmlFor == elt.id);
        });
        if (elt.label) elt.label = $(elt.label);
        if (elt.label && elt.label.innerHTML)
            elt.label.origText = elt.label.innerHTML;
    },

    getElement: function(name) {
        return (this.elements[name]) ? this.elements[name] : false;
    },

    showError: function(elt, message) {
        if (!elt || !elt.label)
            return false;

        elt.label.addClassName('label-error');
        elt.label.innerHTML = elt.label.origText + ': ' + message;

        if (!elt.valid) {
            return false;
        }

        elt.valid = false;
        elt.highlightError(elt);
    },

    hideError: function(elt) {
        if (!elt || !elt.label) return false;

        elt.valid = true;
        elt.label.innerHTML = elt.label.origText;
        elt.label.removeClassName('label-error');
        
        if (elt.effect && elt.effect.cancel) 
            elt.effect.cancel();
            
        if (elt.effect && elt.effect.options.afterFinishInternal)
            elt.effect.options.afterFinishInternal(elt.effect);
    },

    highlightError: function(elt) {
        if (!elt.label)
            return;
        elt.effect = new Effect.Pulsate(elt.label, {duration: 1.5});
    }
};


function submitUploadForm(form) {
    beginUpload(form);
}

function submitEditForm(form) {
    updateImage(form);
}

function validateUploadFile(elt) {
    var validExtensions = ['jpg', 'jpeg', 'gif', 'png'];
    var ext = elt.value.split('.').last();
    if (ext.toLowerCase) ext = ext.toLowerCase();

    if (!$A(validExtensions).include(ext)) {
        return 'select a jpeg, gif or png file';
    }

    return true;
}

function validateEmail(elt) {
    if (elt.value.match(/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/) == null) {
        return 'not a valid email';
    }
    return true;
}

function validateTags(elt) {
    if (elt.value.match(/[^a-zA-Z0-9, ]/) != null) {
        return 'should be alphanumeric';
    }
    return true;
}

function validateTitle(elt) {
    if (elt.value.match(/[^A-Za-z0-9, ]/) != null) {
        return 'should be alphanumeric';
    }
    return true;
}

function dump(obj) {
	var text = '';
	for (prop in obj) {
		text += prop + ': ' + obj[prop] + "\n";
	}

	alert(text);
}
