efobj.InputValidator = new Class({
  initialize: function(className, options){
    this.setOptions({
      errorMsg: 'Validation failed.',
      test: function(field, options){return true}
    }, options);
    this.className = className;
  },

  test: function(field, options){
    if($(field)) return this.options.test($(field), options);
    else return false;
  }
});
efobj.InputValidator.implement(new Options);

efobj.FormValidator = new Class({
  options: {
    singleError: false,
    requiredSpan: new Element('span', { 'class': 'red'}),
    requiredSpanText: '*',
    onFormValidate: function(isValid, form){},
    onElementValidate: function(isValid, field){}
  },

  initialize: function(form, formFieldoptions, errorBox, successBox){
    this.formFieldoptions = formFieldoptions;
    try {
      if(successBox) {
        this.successBox = $(successBox);
        if($('inner_' + this.successBox.id))
          this.successBoxContent = $('inner_' + this.successBox.id);
        else
          this.successBoxContent = this.successBox;
      }
          
      if(errorBox)
        this.errorBox = $(errorBox);
      else
        this.errorBox = $('errorBox');
      if($('inner_' + this.errorBox.id))
        this.errorBoxContent = $('inner_' + this.errorBox.id);
      else
        this.errorBoxContent = this.errorBox;
      this.form = $(form);
      //this.form.addEvent('submit', this.validate.pass([true]), this);
      this.watchFields();
    }
    catch(e){
      efobj.log('initialize');
      efobj.log(e);
    }
  },

  watchFields: function(){
    try{
      for(fieldId in this.formFieldoptions){
        pForm = $j("#"+this.form.id);
        var el = pForm.find("#" +fieldId)[0];
        //var el = $j("#"+this.form.id + " #" +fieldId)[0];
        if(this.formFieldoptions[fieldId].required){
          this.initRequired(fieldId);
        }
      };
    }
    catch(e){
      efobj.log('watchFields');
      efobj.log(e);
    }
  },

  initRequired: function(fieldId){
    var tmpId = fieldId;
    if(this.formFieldoptions[fieldId].destination){
      tmpId = this.formFieldoptions[fieldId].destination;
    }
    if($('t_' + tmpId)){
    var descrElem = $('t_' + tmpId);
      var tmpEL = this.options.requiredSpan.clone();
      tmpEL.setHTML(this.options.requiredSpanText);
      tmpEL.injectInside(descrElem);
    }
  },

  validate: function(force, singleError) {
    this.clearGlobalError();
    if(singleError){
      this.options.singleError = singleError;
    }
    var result = true;
    for(fieldId in this.formFieldoptions){
      pForm = $j("#"+this.form.id);
      var el = pForm.find("#" +fieldId)[0];
      //var el = $j("#"+this.form.id + " #" +fieldId)[0];
      if(!this.validateField(el, force, true)){
        result = false;
        if(!force)
          break;
      }
    };

    //if(!result)
      //TODO check behaviour
      //this.errorBox.scrollIntoView(true);

    return result; 
  },
  
  validateField: function(field, force, full){
    if(this.paused) return true;
    field = $j(field)[0];
    var result = false;
    result = this.formFieldoptions[field.id].validators.some(function(validatorObj) {
      var depends = false;
      if(this.formFieldoptions[field.id].dependsSrc) {
        var tmpButtons = $ES('input[name='+this.formFieldoptions[field.id].dependsSrc+']', this.form.id);
        
        if(tmpButtons && tmpButtons.length>0) {
          for (var i = 0; i < tmpButtons.length; i++) {
            if(tmpButtons[i].value == this.formFieldoptions[field.id].dependsVal && tmpButtons[i].checked) {
              depends = true;
            }
          }
        }
        /* if tmpButtons a normal input field */
        if(tmpButtons && tmpButtons.length==1) {          
          if(tmpButtons[0].value == this.formFieldoptions[field.id].dependsVal) {
            depends = true;
          }
        }
        
        tmpButtons = $E('select[id='+this.formFieldoptions[field.id].dependsSrc+']', this.form.id);
        
        if(tmpButtons && tmpButtons.length>0) {
          for (var i = 0; i < tmpButtons.length; i++) {
            if(tmpButtons[i].selected && tmpButtons[i].value == this.formFieldoptions[field.id].dependsVal){
              depends = true;
            }
          }
        }
      }
            
      var tmpResult = true;
      if($j(field).attr('value') != '' || full) {
        var tmpValidator = this.validators[validatorObj.name];
        
        if(depends || !this.formFieldoptions[field.id].dependsSrc){
          tmpResult = tmpValidator.test(field, this.formFieldoptions[field.id]);
          var labelElem = $(field.id + 'Label');
          if(!tmpResult || validatorObj.name == 'Valid'){
            if(force){
              //this.addGlobalError(validatorObj.msg + "<br /><br />");
              this.addGlobalError(validatorObj.msg);
              field.addClass("error");
              if(labelElem)
               labelElem.addClass("error");
            }
          }
          else{
            field.removeClass("error");
            if(labelElem)
              labelElem.removeClass("error");
          }
        }
      }
      return !tmpResult;
    }, this);

    if(!full)
      this.validate(false);

    return !result;
  },

  addGlobalError: function(message){
    if(this.successBox && !this.successBox.hasClass('hideout'))
      this.successBox.addClass('hideout');
    if(this.errorBox.getParent().hasClass('hideout')){
      this.errorBox.getParent().removeClass('hideout');
      //message = "<br />" + message;
    }
    if((this.options.singleError && this.errorBoxContent.getElements('span').length < 1) || !this.options.singleError){
      var tmpEL = new Element('span');
      tmpEL.setHTML("<li>" + message + "</li>");
      tmpEL.injectInside(this.errorBoxContent);
    }
  },

  clearGlobalError: function(){
    if(!this.errorBox.getParent().hasClass('hideout'))
      this.errorBox.getParent().addClass('hideout')
    this.errorBoxContent.setHTML('');
  },

  stop: function(){
    this.paused = true;
  },

  start: function(){
    this.paused = false;
  }
});
efobj.FormValidator.implement(new Options);
efobj.FormValidator.implement(new Events);

efobj.FormValidator.adders = {
  validators:{},

  add : function(className, options) {
    this.validators[className] = new efobj.InputValidator(className, options);
    //if this is a class
    //extend these validators into it
    if(!this.initialize){
      this.implement({
        validators: this.validators
      });
    }
  }
};
Object.extend(efobj.FormValidator, efobj.FormValidator.adders);
efobj.FormValidator.implement(efobj.FormValidator.adders);


//list of available validators

efobj.FormValidator.add('IsEmpty', {
  test: function(element, options) {
    if(element.type == "select-one"||element.type == "select")
      return (element.selectedIndex >= 0 && element.options[element.selectedIndex].value != "");
    else
      return !((element.getValue() == null) || (element.getValue().length == 0));
  }
});

efobj.FormValidator.add('SpecialChars', {
  test: function(element) {
    return (/^[-a-zA-Z0-9äöüÄÖÜß .`/]*$/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsNumber', {
  test: function (element) {
    if(!((element.getValue() == null) || (element.getValue().length == 0)))
      return (/^[0-9]+$/.test(element.getValue()));
    return true;
  }
});

efobj.FormValidator.add('IsValidLength', {
  test: function (element, options) {
    if(!((element.getValue() == null) || (element.getValue().length == 0)))
      return element.getValue().length >= options.minLength;
    return true;
  }
});

efobj.FormValidator.add('IsValidAddress', {
  test: function (element) {
    return (/^(.*)[0-9]+(.*)$/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsValidAccountNumber', {
  test: function (element) {
    return /^[0-9\*\/ ]*$/.test(element.getValue());
  }
});

efobj.FormValidator.add('IsValidPhoneNumber', {
  test: function (element) {
    return /^[0-9\-\/ ]*$/.test(element.getValue());
  }
});

efobj.FormValidator.add('IsValidEmail', {
  test: function (element) {
    return (/^([a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)$/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsEqualField1', {
  test: function (element, options) {
    return element.getValue() == options.field1.getValue();
  }
});

efobj.FormValidator.add('IsValidDate', {
  test: function (element, options) {
    var result = true;
    if(element.getValue() != '')
      result = (/^(0[1-9]|[12][0-9]|3[01])[-|.](0[1-9]|1[012])[-|.](19|20)[0-9][0-9]$/.test(element.getValue()));
    return result;
  }
});

efobj.FormValidator.add('IsValidPassword', {
  test: function (element) {
    return !((/^[a-z]+$/.test(element.getValue())) || (/^[0-9]+$/.test(element.getValue())));
  }
});

efobj.FormValidator.add('IsFlag', {
  test: function (element, options) {
    return !options.theFlag;
  }
});

efobj.FormValidator.add('FunctionValidator', {
  test: function (element, options) {
    return options.execFunction();
  }
});

// Date validators for separate fields for day, month and year

efobj.FormValidator.add('IsValidSepDate', {
  test: function (element, options) {    
    var result = false;
    var day = options.dayField.getValue();
    var month = options.monthField.getValue();
    var year = options.yearField.getValue();
    var isRequired = options.required;    
    if (!isRequired) {
      result = true;
      if((day.length > 0 || month.length > 0 || year.length > 0)){
        var date = new Date(year, month - 1, day);
        result = ((day == date.getDate()) && ((month - 1) == date.getMonth()) && (year == date.getFullYear()));
      }   
    }else{
      if(year.length == 4 && month.length <= 2 && day.length <= 2){
        var date = new Date(year, month - 1, day);
        result = ((day == date.getDate()) && ((month - 1) == date.getMonth()) && (year == date.getFullYear()));
      }    
    }
   return result;
  }
});

efobj.FormValidator.add('IsSepDateFuture', {
  test: function (element, options) {
    var result = false;
    var day = options.dayField.getValue();
    var month = options.monthField.getValue();
    var year = options.yearField.getValue();
    if(year.length == 4 && month.length <= 2 && day.length <= 2){
      var date = new Date(year, month - 1, day);
      result = date.getTime() < options.currentDate.getTime();
    }
    return !result;
  }
});

efobj.FormValidator.add('IsSepDatePast', {
  test: function (element, options) {
    var result = false;
    var day = options.dayField.getValue();
    var month = options.monthField.getValue();
    var year = options.yearField.getValue();
    if(year.length == 4 && month.length <= 2 && day.length <= 2){
      var date = new Date(year, month - 1, day);
      result = date.getTime() > options.currentDate.getTime();
    }
    return !result;
  }
});

efobj.FormValidator.add('IsSepDateGreaterThen', {
  test: function (element, options) {
    var day = options.dayField.getValue();
    var month = options.monthField.getValue();
    var year = options.yearField.getValue();
    var date = new Date(year, month - 1, day);
    return date.getTime() <= options.maxDate.getTime();
  }
});

efobj.FormValidator.add('IsSepDateLowerThen', {
  test: function (element, options) {
    var day = options.dayField.getValue();
    var month = options.monthField.getValue();
    var year = options.yearField.getValue();
    var date = new Date(year, month - 1, day);
    return date.getTime() >= options.minDate.getTime();
  }
});






























efobj.FormValidator.add('IsEmpty2', {
  test: function(element) {
    if(element.type == "select-one"||element.type == "select")
      return (element.selectedIndex >= 0 && element.options[element.selectedIndex].value != "");
    else
      return !((element.getValue() == null) || (element.getValue().length < 2));
  }
});

efobj.FormValidator.add('NotEmptyMin2', {
  test: function(element) {
    if(element.type == "select-one"||element.type == "select")
      return (element.selectedIndex >= 0 && element.options[element.selectedIndex].value != "");
    else
      return !(element.getValue() != null && element.getValue().length > 0 && element.getValue().length < 2);
  }
});

efobj.FormValidator.add('IsValidCharacterSet', {
  test: function (element) {
    return (/^[a-zA-Z '-]*$/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsValidCaractersNumbers', {
  test: function (element) {
    return (/^[a-zA-Z0-9]*$/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsCapitalLetter', {
  test: function (element) {
    return !(/[A-Z]+/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsAllLetters', {
  test: function (element) {
    return !(/^[a-z]+$/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsAllNumbers', {
  test: function (element) {
    return !(/^[0-9]+$/.test(element.getValue()));
  }
});

efobj.FormValidator.add('IsFirstDigit', {
  test: function (element) {
    return /^[0-9]/.test(element.getValue());
  }
});

efobj.FormValidator.add('IsValidZipCode', {
  test: function (element) {
    return /^[0-9][0-9][0-9][0-9]?[a-zA-Z][a-zA-Z]$/.test(element.getValue());
  }
});



efobj.FormValidator.add('IsNotDefault', {
  test: function (element, options) {
    return element.getValue().length > 0 && element.getValue() != options.defaultText;
  }
});


efobj.FormValidator.add('IsNullLength', {
  test: function (element, options) {
    return element.getValue().length == 0;
  }
});

efobj.FormValidator.add('IsNotEqualField1', {
  test: function (element, options) {
    return element.getValue() != options.field1.getValue();
  }
});

efobj.FormValidator.add('IsNotEqualField2', {
  test: function (element, options) {
    return element.getValue() != options.field2.getValue();
  }
});

efobj.FormValidator.add('IsNotEqualField1', {
  test: function (element, options) {
    return element.getValue() != options.field1.getValue();
  }
});

efobj.FormValidator.add('IsValidIdx', {
  test: function (element, options) {
    return !isValidSubject();
  }
});

efobj.FormValidator.add('IsChecked', {
  test: function(element) {
    return element.checked;
  }
});

efobj.FormValidator.add('IsSelectGT0', {
  test: function(element) {
    return element.selectedIndex > 0;
  }
});

efobj.FormValidator.add('Valid', {
  test: function (element) {
    return true;
  }
});

efobj.FormValidator.add('isValidNumberRange', {
  test: function (element, options) {
    var lower = options.lower;
    var upper = options.upper;
    return (lower <= upper && element.getValue() >= lower && element.getValue() <= upper);
  }
});