var Validator = {}
Validator.Base = function() {};
Validator.Base.prototype = {
  baseInitialize: function(element, update, func, options) {
    this.element     = $(element);
    this.update      = $(update);
    this.func        = func;
    this.valid       = false;
    this.defaultResult = this.update.innerHTML;

    if (this.setOptions)
      this.setOptions(options);
    else
      this.options = options || {};

    this.options.frequency    = this.options.frequency || 0.4;
    this.options.onShow       = this.options.onShow || function(element, update){};
    this.options.minCheckLength = this.options.minCheckLength || 0;

    this.observer = null;
    
    this.element.setAttribute('autocomplete','off');

    EventX.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));

    if (this.element.value.length > 0) {
        setTimeout(this.validate.bind(this), 500);
    }
  },

  onKeyPress: function(event) {
    if (event.keyCode==EventX.KEY_TAB || event.keyCode==EventX.KEY_RETURN) {
        return;
    }

    if (this.observer) clearTimeout(this.observer);
    this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
  },
 
  onObserverEvent: function() {
    if (this.getValue().length >= this.options.minCheckLength) {
        this.validate();
    } else {
        this.setMessage('');
    }
  },

  getValue: function() {
	return this.element.value;
  },

  setValue: function(v) {
	this.element.value = v;
	this.validate();
  },

  setMessage: function(message) {
    if (message.length == 0) {
		message = this.defaultResult;
    }
	this.update.innerHTML = message;	
  },

  isValid: function() {
	return this.valid;
  }

}

Ajax.Validator = Class.create();
Object.extend(Object.extend(Ajax.Validator.prototype, Validator.Base.prototype), {
  initialize: function(element, update, func, options) {
    this.baseInitialize(element, update, func, options);
    this.options.asynchronous  = true;
    this.options.onComplete    = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url                   = this.options.url;
  },

  validate: function() {
    new Ajax.Request(this.url + this.getValue(), this.options);
  },

  onComplete: function(request) {
    this.valid = this.func(request.responseXML, request.responseText, this);
  }

});

Ajax.CaptchaValidator = Class.create();
Object.extend(Object.extend(Ajax.CaptchaValidator.prototype, Validator.Base.prototype), {
  initialize: function(element, captchaid, update, func, options) {
    this.baseInitialize(element, update, func, options);
    this.options.asynchronous  = true;
    this.options.onComplete    = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url                   = this.options.url;
    this.captchaid = captchaid;
  },

  validate: function() {
    new Ajax.Request(this.url + this.getValue() + '&id='+this.captchaid, this.options);
  },

  onComplete: function(request) {
    this.valid = this.func(request.responseXML, request.responseText, this);
  }

});

Validator.Local = Class.create();
Validator.Local.prototype = Object.extend(new Validator.Base(), {
  initialize: function(element, update, func, options) {
    this.baseInitialize(element, update, func, options);
  },

  validate: function() {
	this.valid = this.func(this.element.value, this);
  }
});