(
  function($)
  {
    var options =
    {
      'icon_set': 'ICON_SET',
      'javascript': 1,
      'checkbox': []
    };

    var methods =
    {
      init: function(opts)
      {
        if (opts)
        {
          $.extend(options, opts);
        }

        if ($(this).find(':input[name=validate-options]').length)
        {
          $(this).each(function(){$(this).validate('form')});
        }
      },

      form: function ()
      {
        $(this).validate('regexp');

        var opts = this.find(':input[name=validate-options]').val();
        if (opts)
        {
          eval('opts = ' + opts);
          $.extend(options, opts);
        }

        $(this).validate('indicators');

        //this.attr('onsubmit', function(){return false}); // IE7 ERROR
        this.submit(function(){return $(this).validate('send');});
        this.find(':input').each(function(){$(this).validate('input');});
      },

      indicators: function ()
      {
        options.indicator = {};
        var img = new Image();
        img.src = options.icon_set + '/delete.png';
        options.indicator.invalid = img;

        var img = new Image();
        img.src = options.icon_set + '/valid.png';
        options.indicator.valid = img;
      },

      input: function ()
      {
        var validation = this.attr('data-validation');

        if (this.attr('type') == 'radio')
        {
          return false;
        }

        if (validation)
        {
          eval('validation = ' + validation);

          // attach img and tool tips
          var img = $(options.indicator.invalid).clone();
          $(img).validate('hints');

          if (this.attr('type') != 'checkbox')
          {
            this.after(img);
          }
          else
          {
            var n = this.attr('name');
            n = n.substr(0, n.length - 2);
            var form = this.parents('form');
            var input = form.find(':input[name=' + n  + '_checkbox]');
            if (!input.attr('data-image'))
            {
              input.attr('data-image', 1);
              input.after(img);
              img.attr('id', n + '_indicator');
            }
          }

          // attach listener
          var test = function(){$(this).validate('test_input', validation, img)};
          var type = this.attr('type');
          var node = this.get(0).nodeName.toLowerCase();

          switch (true)
          {
          case node == 'select':
          case type == 'checkbox':
            this.change(test);
          break;

          default:
            this.click(test);
            this.keyup(test);
            this.change(test);
          break;
          }

          $(this).validate('test_input', validation, img);
        }
      },

      hints: function()
      {
        $(this).qtip({content: 'Loading Hints ....'});
      },

      test_input: function(validation, img, ajax)
      {
        var check_rules = true;

        // test for unique rule
        if (validation.hasOwnProperty('unique'))
        {
          if (!ajax)
          {
            check_rules = false;
            $(this).validate('unique', validation, img);
          }
        }

        if (check_rules)
        {
          var valid = [];
          var hints = [];

          for (rule in validation)
          {
            var result = $(this).validate('rule', rule, validation);
            valid.push(result.valid);
            if (!result.valid)
            {
              hints.push(result.hint);
            }
          }

          if (this.attr('type') == 'checkbox')
          {
            var n = this.attr('name');
            n = n.substr(0, n.length - 2);
            img = $('#' + n + '_indicator');
          }

          if (hints.length)
          {
            $(img).attr('src', options.indicator.invalid.src);
          }
          else
          {
            $(img).attr('src', options.indicator.valid.src);
            hints.push('Valid');
          }

          $(img).qtip("destroy");
          $(img).qtip({content: hints.join('<br>')});
        }
      },

      unique: function (validation, img)
      {
        var option = validation.unique;
        option.value = this.val();
        option.form = $(this).parents('form').attr('name');
        option.input = this.attr('name');

        var success = function (result)
        {
          eval('result = ' + result);
          var form = $(document).find('form[name="' + result.form + '"]');
          var input = form.find(':input[name=' + result.input + ']');
          input.attr('data-unique', result.unique);

          // recall test_input
          input.validate('test_input', validation, img, true);
        }

        var call =
        {
          url: '/resources/php/ajax/unique.php',
          data: option,
          success: success
        }
        $.ajax(call);
      },

      rule: function(rule, validation)
      {
        if (!options.javascript)
        {
          return {hints: '', valid: 1}
        }

        var value = this.val();

        return $(this).rule(options, rule, validation, value);
      },

      send: function ()
      {
        var tested = 0;
        var passed = 0;
        var regex = new RegExp('valid.png$');
        var inputs = [];
        this.find(':input').each
        (
          function()
          {
            var n = $(this).attr('name');
            var validation = $(this).attr('data-validation');
            if (validation)
            {
              if ($.inArray(n, inputs) < 0)
              {
                eval('validation = ' + validation);
                var img = $(this).parent().children('img');

                if ($(this).attr('type') == 'checkbox')
                {
                  img = n.substr(0, n.length - 2);
                  img = $('#' + img + '_indicator');
                }

                $(this).validate('test_input', validation, img);

                if (regex.test(img.attr('src')))
                {
                  passed ++;
                }

                tested ++;
                inputs.push(n);
                //console.log(tested, passed);
              }

            }
          }
        );

  			var now = new Date();
      	var unix = now.getTime() / 1000;
      	var valid = document.createElement('input');
      	valid.type = 'hidden';
      	valid.name = 'UNIX' + (now.getMonth() + 1) + now.getDate();
      	valid.value = Math.round(unix);
      	this.append(valid);

        var upload = false;
        this.find(':input[type=file]').each
        (
          function ()
          {
            if ($(this).val().length)
            {
              upload = true;
            }
          }
        )

        if (upload)
        {
          openuploadgif();
        }

        return passed == tested;
      },

      regexp: function()
      {
        options.regex = {};
        $('form[name=regexp]').find(':input').each
        (
          function ()
          {
            var name = $(this).attr('name');
            options.regex[name] = new RegExp($(this).val(), 'i');
          }
        );
      }
    };

    $.fn.validate = function(method)
    {
      if (methods[method])
      {
        return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
      }
      else if(typeof method === 'object' || !method)
      {
        return methods.init.apply(this, arguments);
      }
      else
      {
        $.error( 'Method ' +  method + ' does not exist on jQuery.validate' );
      }
    };
  }
)
(jQuery);

