ggobj.FormValidator = new Class({
  Implements: [Options, Events],

  options: {
    singleError: false,
    requiredSpan: new Element('span', { 'class': 'red'}),
    requiredSpanText: '*',
    onFormValidate: function(isValid, form){},
    onElementValidate: function(isValid, field){}
  },

  initialize: function(form, formFieldoptions, errorBox, successBox, doNotScroll){
    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.watchFields();
    }
    catch(e){
      ggobj.log(e);
    }
  },

  watchFields: function(){
    try{
      for(fieldId in this.formFieldoptions){
        var el = $(fieldId);
        if(this.formFieldoptions[fieldId].required){
          this.initRequired(fieldId);
        }
      };
    }
    catch(e){
      ggobj.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.set('html', 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){
      var el = $(fieldId);
      if(!this.validateField(el, force, true)){
        result = false;
        if(!force)
          break;
      }
    };
    if(!result){
      this.errorBox.scrollIntoView(true);
    }  
    return result; 
  },

  validateField: function(field, force, full){
    //alert(field.id + '|' + force + '|' + full)
    if(this.paused) return true;
    field = $(field);
    var result = false;

    result = this.formFieldoptions[field.id].validators.some(function(validatorObj){
      var depends = false;
      if(this.formFieldoptions[field.id].dependsSrc){
        var tmpButtons = $('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;
            }
          }
        }

        tmpButtons = $(this.formFieldoptions[field.id].dependsSrc, this.form.id);

        if (tmpButtons.value == this.formFieldoptions[field.id].dependsVal){
         depends = true;
        }

        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;
      field.removeClass('form_error');
      if((field.get('value') != '' || full) && !this.formFieldoptions[field.id].dependsField){
        var tmpValidator = this.validators[validatorObj.name];

        if(depends || !this.formFieldoptions[field.id].dependsSrc){
          tmpResult = tmpValidator.test(field, this.formFieldoptions[field.id]);

          if(!tmpResult || validatorObj.name == 'Valid'){
            if(force){
              this.addGlobalError(validatorObj.msg + "<br />", field);
            }
          }
        }

       //control payment data with depends field
       } else if ((field.get('value') != '' || full) && this.formFieldoptions[field.id].dependsField){
         element = field.get('value');
         options = $(this.formFieldoptions[field.id].dependsField).get('value');
         srcval = $(this.formFieldoptions[field.id].dependsSrc).get('value');
         dpval = this.formFieldoptions[field.id].dependsVal;

         if (srcval == dpval){
         
           if($(this.formFieldoptions[field.id].fieldpair1)){
             fieldpairvalue = $(this.formFieldoptions[field.id].fieldpair1).get('value');
             if ((element == '' && fieldpairvalue != '')){        
               this.addGlobalError(validatorObj.msg2 + "<br />", field);
              return tmpResult; 
     }
   } 

         if(element.length == 0 && options.length == 0){
           this.addGlobalError(validatorObj.msg + "<br />", field);
           return tmpResult; 
         }

        }
         
       } 

      return !tmpResult;

    }, this);

    if(!full)
      this.validate(false);

    return !result;
  },

  addGlobalError: function(message, theField){
    if(this.successBox && !this.successBox.hasClass('hideoutbox'))
      this.successBox.addClass('hideoutbox');
    if(this.errorBox.hasClass('hideoutbox')){
      this.errorBox.removeClass('hideoutbox');
      message = message;
    }
    if((this.options.singleError && this.errorBoxContent.getElements('span').length < 1) || !this.options.singleError){
      var tmpEL = new Element('span');
      tmpEL.set('html', message);
      tmpEL.injectInside(this.errorBoxContent);
    }
    if (theField) {
      theField.addClass('form_error');
    }
  },

  clearGlobalError: function(){
    if(!this.errorBox.hasClass('hideoutbox'))
      this.errorBox.addClass('hideoutbox')
    this.errorBoxContent.set('html', '');
  },

  stop: function(){
    this.paused = true;
  },

  start: function(){
    this.paused = false;
  },
  

  validators: {
    FunctionValidator: {
      test: function (element, options) {
        return options.execFunction();
      }
    },
    
    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.get('value') == null) || (element.get('value').length == 0));
      }
    },

    IsChecked: {
      test: function(element) {
        return (element.checked);
      }
    },
    
    IsNumber: {
      test: function (element) {
        if(!((element.get('value') == null) || (element.get('value').length == 0)))
          return (/^[0-9]+$/.test(element.get('value')));
          return true;
      }
    },

    IsNumberorEmpty: {
      test: function (element) {
        if(element.get('value').length > 0){
          return (/^[0-9]+$/.test(element.get('value')));
        } else {
          return true;
        }  
      }
    },

    IsValidPhoneNumber: {
      test: function (element) {
        return /^[0-9\-\/ ]*$/.test(element.get('value'));
      }
    },

    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.get('value')));
      }
    },

    IsEqualField1: {
      test: function (element, options) {
        return element.get('value') == options.field1.get('value');
      }
    },

    IsDependsField1: {
      test: function (element, options) {
        if (!((element.get('value') == null || (element.get('value').length == 0)) && (options.field1.get('value') == null || (options.field1.get('value').length == 0)))){        
          return true;
        }
      }
    },

    FieldPairs: {
      test: function (element, options) {
        if (!(element.get('value').length == 0 && options.fieldpair1.get('value').length > 0) || element.get('value').length > 0 && options.fieldpair1.get('value').length == 0){        
          return true;
        }
      }
    },


    IsValidLength: {
      test: function (element, options) {
        if(!((element.get('value') == null) || (element.get('value').length == 0)))
          return element.get('value').length >= options.minLength;
        return true;
      }
    },

    IsValidLengthorEmpty: {
      test: function (element, options) {
        if(element.get('value').length > 0)
          return element.get('value').length >= options.minLength;
        return true;
      }
    },


    IsValidMaxLength: {
      test: function (element, options) {
        if(!((element.get('value') == null) || (element.get('value').length == 0)))
          return element.get('value').length <= options.maxLength;
        return true;
      }
    },

    IsValidPassword: {
      test: function (element, options) {
       var letter = "";
       var content = element.get('value');
       var intval = 0;
       var stringval = 0;
       for (i = 0; i < content.length; i++){
         letter = content.substring(i,i+1);
         if (/^[0-9]*$/.test(letter)){
           intval = intval+1;
         }  
         if (/^[a-zA-Z]*$/.test(letter)){
           stringval = stringval+1;
         }  
       }
        if(intval == 0 || stringval == 0)
          return false;
        return true;
      }
    },
    // Date validators for separate fields for day, month and year

    IsValidSepDate: {
      test: function (element, options) {
        var result = false;
        var day = options.dayField.get('value');
        var month = options.monthField.get('value');
        var year = options.yearField.get('value');

        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;
      }
    },

    IsSepDateLowerThen: {
      test: function (element, options) {
        var day = options.dayField.get('value');
        var month = options.monthField.get('value');
        var year = options.yearField.get('value');
        var date = new Date(year, month - 1, day);        
        return date.getTime() >= options.minDate.getTime();
      }
    },
    IsSepDateGreaterThen: {
      test: function (element, options) {
        var day = options.dayField.get('value');
        var month = options.monthField.get('value');
        var year = options.yearField.get('value');
        var date = new Date(year, month - 1, day);
        return date.getTime() <= options.maxDate.getTime();
      }
    },

    SpecialChars: {
      test: function(element) {
        return (/^[-a-zA-Z0-9äöüÄÖÜß .\'/]*$/.test(element.get('value')));
      }
    }
  }
});
