(
  function($)
  {
    $.fn.rule = function(options, rule, validation, value)
    {
      var result =
      {
        valid: 0,
        hint: 'Rule <i>' + rule + '</i> not found'
      }

      var option = validation[rule];
      var required = validation.hasOwnProperty('required');
      var number = validation.hasOwnProperty('number');
      var skip = validation.hasOwnProperty('skip');
      var form = this.parents('form');

      // skip empty not required
      switch (true)
      {
      //case 1 == 1:
      case skip && validation.skip == value:
      case !value.length && !required:
        return {valid: 1};
      break;
      }

      if (this.attr('type') == 'checkbox')
      {
        value = '';
        form.find(':input[name="' + $(this).attr('name') + '"]:checked').each
        (
          function ()
          {
            value += $(this).val();
          }
        );
      }

      switch (rule)
      {
      case 'email':
        result.hint = options.hint.email;
        result.valid = options.regex.email.test(value);
      break;

      case 'equals':
        result.hint = options.hint.equals + ' ' + option.label;
        var test = form.find(':input[name=' + option.input + ']').val();
        result.valid = test == value;
      break;

      case 'minimum':
        var hint = [options.hint.minimum];
        hint.push(number ? 'value' : 'characters');
        hint.push(option);
        result.hint = hint.join(' ');
        result.valid = number ? value >= option : value.length >= option;
      break;

      case 'maximum':
        var hint = [options.hint.maximum];
        hint.push(number ? 'value' : 'characters');
        hint.push(option);
        result.hint = hint.join(' ');
        result.valid = number ? value <= option : value.length <= option;
      break;

      case 'notequal':
        result.hint = options.hint.notequal + ' ' + option.label;
        var test = form.find(':input[name=' + option.input + ']').val();
        result.valid = test != value;
      break;

      case 'number':
        result.hint = options.hint.number;
        var regex = new RegExp('^[0-9]+$', 'g');
        result.valid = regex.test(value);
      break;

      case 'password':
        result.valid = 1;
        var hints = [];

        // test same as username
        var username = form.find(':input[name=username]').val();
        if (username == value)
        {
          hints.push(options.hint.password.username);
        }

        // length
        if (value.length < 8)
        {
          hints.push(options.hint.password.length);
        }

        // numbers
        if (value.replace(/[^0-9]/g, '').length < options.rule.password.int)
        {
          hints.push(options.hint.password.int);
        }

        // special characters
        var regexp = new RegExp('[^' + options.rule.password.char + ']', 'g');
        if (!value.replace(regexp, '').length)
        {
          hints.push(options.hint.password.char);
        }

        if (value == 'keepcurrent')
        {
          hints = [];
        }

        result.valid = hints.length ? 0 : 1;
        result.hint = hints.join('<br>');
      break;

      case 'regexp':
        var regexp = new RegExp(validation[rule].regexp, 'gi');
        result.hint = validation[rule].hint;
        result.valid = regexp.test(value);
      break;

      case 'required':
        result.hint = options.hint.required;
        result.valid = value.length ? 1 : 0;
      break;

      case 'unique':
        result.hint = options.hint.unique;
        result.valid = this.attr('data-unique') == 0 ? 0 : 1;
      break;

      case 'username':
        var hints = [];

        // test for disallowed
        var regex = new RegExp('[^' + options.rule.username.char + ']', 'i');
        if (value.search(regex) > -1)
        {
          hints.push(options.hint.username.char);
        }

        // test for length
        if (value.length < options.rule.username.length)
        {
          hints.push(options.hint.username.length);
        }

        result.valid = hints.length ? 0 : 1;
        result.hint = hints.join('<br>');
      break;

      case 'skip':
        result.hint = 'placeholder';
        result.valid = true;
      break;

      case 'website':
        result.hint = options.hint.website;
        var regex = new RegExp('^[0-9]+$', 'g');
        result.valid = regex.test(value);
      break;

      case 'extension':
        var hint = [options.hint.extension];
        hint.push('[' + option + ']');
        result.hint = hint.join(' ');
        var option = option.split(',');
        var value = value.split('.');
        value = value[value.length - 1];
        value = value.toLowerCase();
        result.valid = false;
        for (var i = 0; i < option.length; i ++)
        {
          if (value == option[i])
          {
            result.valid = true;
          }
        }
      break;
      }

      return result;
    }
  }
)
(jQuery)
