/*
 * Validation plugin for the Securepoint DynDNS-Service
 */

(function($) {
    $.fn.validate = function(options) {
        settings = $.extend({
            rule: ['required'],
            minlength: 0,
            maxlength: 999999,
            minval: 0,
            maxval: 999999,
            equalTo: $( [] ),
            optional: false
        }, options);

        rules = {
            required: function(element) {
                var value = $(element).val()
                switch( element.nodeName.toLowerCase() ) {
                    case 'select':
                        // could be an array for select-multiple or a string, both are fine this way
                        var val = $(element).val();
                        return val && val.length > 0;
                    case 'input':
                        if ( checkable(element) )
                            return getLength(value, element) > 0;
                    default:
                        return $.trim(value).length > 0;
                }
            },

            minlength: function(element) {
                return getLength($.trim($(element).val()), element) >= settings.minlength;
            },

            maxlength: function(element) {
                return getLength($.trim($(element).val()), element) <= settings.maxlength;
            },

            rangelength: function(element) {
                var value = $(element).val();
                var length = getLength(element);
                return ( length >= settings.minlength && length <= settings.maxlength );
            },

            hostname: function(element) {
                return /^([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$/.test($(element).val());
            },

            fqdn: function(element) {
                return /^([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.([a-z0-9][a-z0-9]+)(\.?)$/i.test($(element).val());
            },

            secondlevel_domain: function(element) {
                return /^([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.([a-z0-9][a-z0-9]+)$/.test($(element).val());
            },

            email: function(element) {
                // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
                return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test($(element).val());
            },

            url: function(element) {
                // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
                return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test($(element).val());
            },

            ip: function(element) {
                return /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/.test($(element).val());
            },

            alphanum: function(element) {
                return /^[a-z0-9]+$/i.test($(element).val());
            },

            equalTo: function(element) {
                value = $(element).val();
                var target = $(settings.equalTo);
                return (value.length > 0) && (value == target.val());
            },

            has_letter: function(element) {
                return /[a-z]+/i.test($(element).val());
            },

            has_lowercase: function(element) {
                return /[a-z]+/.test($(element).val());
            },

            has_uppercase: function(element) {
                return /[A-Z]+/.test($(element).val());
            },

            has_number: function(element) {
                return /[0-9]+/.test($(element).val());
            },

            has_special: function(element) {
                return /[^a-zA-Z0-9]/.test($(element).val());
            },

            always_true: function(element) {
                return true;
            },

            range: function(element) {
                return ($(element).val() >= settings.minval && $(element).val() <= settings.maxval)
            }
        }

        checkable = function( element ) {
            return /radio|checkbox/i.test(element[0].type);
        }

        findByName = function( name ) {
            // select by name and filter by form for performance over form.find("[name=...]")
            var form = this.currentForm;
            return $(document.getElementsByName(name)).map(function(index, element) {
                return element.form == form && element.name == name && element  || null;
            });
        }

        getLength = function(element) {
            switch( element[0].nodeName.toLowerCase() ) {
            case 'select':
                return $("option:selected", element).length;
            case 'input':
                if( checkable( element) )
                    return findByName(element.name).filter(':checked').length;
            }
            return $(element).val().length;
        }

        var clean = true;
        var oneEl = $(this[0])[0];
        $.each(settings.rule, function() {
            var errorEl = $('#validate-'+$(oneEl).attr('id')+' .v-'+this);
            if (rules[this]($(oneEl)) === false) {
                if (!settings.optional) {
                    clean = false;
                    $(oneEl).addClass('ui-state-error');
                }
                if (errorEl.length != 0) {
                    errorEl.addClass('icon-bad');
                    errorEl.removeClass('icon-good');
                }
            } else {
                if (clean == true && !settings.optional)
                    $(oneEl).removeClass('ui-state-error');
                
                if (errorEl.length != 0) {
                    errorEl.addClass('icon-good');
                    errorEl.removeClass('icon-bad');
                }
            }
        });
        return clean;
    }
})(jQuery);

