Formvalidator = new Class({

    // Global properties
    id:         null,
    valid:      true,
    messages:   [],
    _regexType: /:.*$/g,
    _regexAttr: /^.*:/g,

    // Methods
    initialize: function(id, options) {
        this.id = id;
        Window.addEvent('domready', this.prepare.bind(this));
    },
    
    prepare: function() {
        if (!$(this.id)) {
            return false;
        }
        $(this.id).addEvent('submit', this.validate.bind(this));
    },
    
    validate: function(evt) {
        evt = new Event(evt);

        this.messages = new Array();
        
        $ES('label', $(this.id)).each(function(label) {
            var validators = label.getProperty('class').split(' ');
            var field      = label.getProperty('for');
            var name       = $E('span', label);
            validators.each(function(validator) {
                var type   = validator.replace(this._regexType, '').toLowerCase();
                var attr   = validator.replace(this._regexAttr, '');
                this._validateField(field, name, type, attr);
            }.bind(this));
        }.bind(this));
        
        if (this.messages.length) {
            this._displayErrors();
            evt.stop();
        }
    },
    
    _displayErrors: function() {
        alert(this.messages.join("\n"));
        return false;
    },
    
    _validateField: function(field, name, type, attr) {
        if (!$(field)) {
            return false;
        }
        if (name) {
            name = name.innerHTML;
        }
        value = $(field).getValue();
        switch(type) {
            case "regexp":
                var regex = new RegExp(attr, "g");
                if (value != '' && !regex.test(value)) {
                    this.messages.push(this._getErrorMessage(field, 'Please ensure you have entered the correct value for "' + name + '"'));
                }
                break;
    
            case "email":
                var regex = /^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/;
                if (value != '' && !regex.test(value)) {
                    this.messages.push(this._getErrorMessage(field, '\'' + value + '\' is not a valid email address. Please enter another'));
                }
                break;
            
            case "numeric":
                var regex = /^[0-9\.]+$/;
                if (value != '' && !regex.test(value)) {
                    this.messages.push(this._getErrorMessage(field, 'Please enter a valid number for "' + name + '"'));
                }
                break;
            
            case "required":
                if (value == '') {
                    this.messages.push(this._getErrorMessage(field, 'Please enter a value for "' + name + '"'));
                }
                break;
        }
    },
    
    _getErrorMessage: function(field, msg) {
        var alt = $(field).getProperty('alt');
        return (alt) ? alt : msg;
    }
});
