/**
 * Script: form.validator.js
 * Last update: May 22, 2008
 *
 * Options:
 *  customErrorMsgClass: define your own errorMsgClass (not yet implemented)
 *  responseElement: id of element that will display (error) messages
 *
 * Requires:
 *  A hidden input field with all required fields. This input field is used in PHP backend too for validation. If not supplied, return is true by default!
 *
 * Usage:
 *  var validateForm = new formValidator('thisForm', {});
 */
var formValidator = new Class({
  Implements: [Options],

  options: {
    customErrorMsgClass: '',
    responseElement: '',
    validationErrors: 'below',
		validateLanguage: 'nl'
  },

  initialize: function(whichForm, options) {
    this.setOptions(options);
    this.form = $(whichForm);
    this.numOfErrors = 0;

		this.reqFieldsContainer = this.form.getElement('input[name=required]');
    if (this.reqFieldsContainer.length == 0) {
      //Missing element with required fields, this will return true by default!
      return true;
    }
    this.reqFields = this.reqFieldsContainer.value.split(',');

    this.errorheaderId = 'errorheader';
    this.errorMsgClass = 'errormsg';
    this.errorImg = '/assets/images/iconExclamationMarkRoundGrey.png';
    this.errorImgAlt = 'Error';
    this.headerSet = false;
		this.responseSet = false;

    if (this.options.validateLanguage == 'nl') {
      this.errorheaderMsg = 'Corrigeer a.u.b. de gemarkeerde velden!';
      this.errorMsgRequired = 'Dit veld is verplicht.';
      this.errorMsgRequiredShort = 'Verplicht!';
      this.errorMsgEmail = 'Dit e-mailadres is onjuist.'
      this.errorMsgEmailShort = 'Onjuist e-mailadres.'
      this.errorImgTitle = 'Dit veld bevat een fout';
      this.errorMsgAgreement = 'Je dient akkoord te gaan met de voorwaarden.';
    } else {
      this.errorheaderMsg = 'Please correct the marked fields!';
      this.errorMsgRequired = 'This field is required.';
      this.errorMsgRequiredShort = 'Required!';
      this.errorMsgEmail = 'This e-mail address is not correct.'
      this.errorMsgEmailShort = 'E-mail incorrect.'
      this.errorImgTitle = 'This field has an error';
      this.errorMsgAgreement = 'You need to agree to our agreement.';
    }

    this.addBlurEvents();
  },

  addBlurEvents: function() {
    this.fields = this.form.getElements('input[type=text]');
    this.fields.extend(this.form.getElements('input[type=checkbox]'));
    this.fields.extend(this.form.getElements('textarea'));
    this.fields.each(function(elm) {
      elm.removeEvents('blur');
			elm.addEvent('blur', function() {
				checkValue = elm.getProperty('rel');
				switch(checkValue)
				{
					case 'float':
						this.checkFloat(elm);	
					  break;
					case 'int':
						this.checkInt(elm);	
					  break;
					case 'currency':
					  this.checkCurrency(elm);
				    break;
					case 'allCaps':
						this.setAllCaps(elm);	
					  break;
					case 'elfproef':
						this.elfproef(elm);	
					  break;
					case 'bsn':
						this.BSNCheck(elm);	
					  break;
					case 'beschikkingsnr':
						this.checkBeschikkingsnummer(elm);	
					  break;
				}  
	      //this.validateField(this);
      }.bind(this));
    }.bind(this));
  },

  validateField: function(elm) {
    this.clearError(elm);
    if (elm.get('tag') == 'textarea') {
      if (elm.value == '' && this.reqFields.contains(elm.name)) {
        this.addError(elm, 'required');
      }
    } else {
      switch (elm.type.toLowerCase()) {	
        case 'text':
        case 'password':
        case 'textarea':
          if (elm.name == 'emailaddress' && elm.value != '' && !this.isEmailAddress(elm.value)) {
            this.addError(elm, 'emailaddress');
          } else if (elm.value == '' && this.reqFields.contains(elm.name)) {
            this.addError(elm, 'required');
          }
          break;
        case 'checkbox':
          if (!elm.checked && this.reqFields.contains(elm.id) && (elm.name != 'agreement')) {
            this.addError(elm, 'required');
          } else if (!elm.checked && this.reqFields.contains(elm.id) && (elm.name== 'agreement')) {
            this.addError(elm, 'agreement');
          }
          break;
        case 'select-one':
          if (!elm.selectedIndex && elm.selectedIndex == 0) {
            this.addError(elm);
          }
          break;
      }
    }
  },

  validateAllFields: function() {
    //clean up previous check
	  if (this.responseSet)
	  {
      this.options.responseElement.setStyle('visibility', 'hidden');
			this.options.responseElement.empty();
			this.headerSet = false;
			this.responseSet = false;
    }
    this.numOfErrors = 0;
    //start check
    this.allFieldsValidate = true;
    this.fields.each(function(elm) {
      if (elm.name != 'required') {
        this.validateField(elm);
      }
    }.bind(this));
    this.allFieldsValidate = false;
    if (this.numOfErrors == 0) {
      this.numOfErrors = 0;
      this.headerSet = false;
      return true; //there are no errors
    } else {
      //fix height div
			if ($('changingheightformcontainer')) {
      	//divCorrectToNewHeight('changingheightformcontainer'); //divName should be selected dynamically (geeft nu errors bij andere forms met container divs etc.)
        //console.log('fix height div');
			}
			return false; //there are errors
    }
  },

  addError: function(elm, type) {
    this.numOfErrors++;
    var shortText = false;

    if (this.allFieldsValidate && !this.headerSet) {
			//Create error message and insert into response element
			new Element('p', {
			  'class': 'errorheader'
			}).set('html', this.errorheaderMsg).inject(this.options.responseElement);
			//this.options.responseElement.set('html', this.errorheaderMsg);
			//this.options.responseElement.addClass('formerror');
			this.options.responseElement.setStyle('visibility', 'visible');
			this.headerSet = true;
    }

    if (this.options.validationErrors == 'inline') {
      elm.setStyle('border', '2px solid red');
    } else {
      //error image
			var errorIndicatorImg = new Asset.image(this.errorImg, {alt: this.getErrorText(type, shortText), 'title': this.getErrorText(type, shortText), 'class': this.errorMsgClass});
      /*var errorIndicatorImg = new Element('img', {
        'src': this.errorImg,
        'alt': this.getErrorText(type, shortText),
        'title': this.getErrorText(type, shortText),
				'class': this.errorMsgClass
      });*/
			
			$(errorIndicatorImg).inject($(elm.getParent()), 'bottom');
			errorIndicatorImg.setStyles({'top': elm.getCoordinates().top, 'z-index': 999999999, 'position':'absolute', 'visibility':'hidden'});   
			$(errorIndicatorImg).setStyles({'left': (elm.getCoordinates().left-(errorIndicatorImg.getCoordinates().width+4)), 'visibility': 'visible'});
			
			
			//$(errorIndicatorImg).inject($(document.body), 'bottom');
			//$(errorIndicatorImg).setStyles('z-index': 999999999, 'position':'absolute'}).setStyles(elm.getCoordinates());    

      /*//Error container + text and image
      var elmWidth = elm.getStyle('width').toInt();
      if (elmWidth < 150) {
        var shortText = true;
      }
      var errorIndicator = new Element('div');
      $(errorIndicator).addClass(this.errorMsgClass);
      $(errorIndicatorImg).inject(errorIndicator);
      $(errorIndicator).appendText(this.getErrorText(type, shortText));
      $(errorIndicator).setStyles({'width': elmWidth, 'z-index': 999999999, 'position':'absolute'}).setStyles(elm.getCoordinates());    
      $(errorIndicator).inject($(document.body), 'bottom');*/
    }
    this.responseSet = true;
  },

  getErrorText: function(type, shortText) {
    if (type == 'emailaddress') {
      if (shortText) {
        return this.errorMsgEmailShort;
      } else {
        return this.errorMsgEmail;
      }
    } else if (type == 'required') {
      if (shortText) {
        return this.errorMsgRequiredShort;
      } else {
        return this.errorMsgRequired;
      }
    } else if (type == 'agreement') {
      return this.errorMsgAgreement;
    }
  },

  clearError: function(elm) {
    if (this.options.validationErrors == 'inline') {
      elm.setStyle('border', '1px solid #999');
    } else {
      if (elm.getNext() && elm.getNext().hasClass(this.errorMsgClass)) {
        elm.getNext().remove();
      }
    }
  },
	
	clearErrors: function() {
		this.numOfErrors = 0;
		$$('.'+this.errorMsgClass).destroy();
	},

  isEmailAddress: function(str) {
    return str.match(/^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/);
  },
	
	checkFloat: function(elm) {
		var value = elm.value;
		value = this.trim(value);
		value = value.replace(' ', '').replace(',', '.');
		value = value.toFloat();
		validate = this.validateFilter('float', value);
		if (!validate) value = '';
		elm.value = value;
	},

	checkInt: function(elm) {
		var value = elm.value;
    value = this.trim(value);
    value = value.replace(' ', '');
		value = value.toInt();
		if (isNaN(value)) value = '';
		elm.value = value;
	},
	
  checkCurrency: function(elm) {
		var value = elm.value;
		value = this.trim(value);
		value = value.replace(' ', '').replace(',', '.');
    value = new Number(value);
    value = value.toFixed(2);
		validate = this.validateFilter('currency', value);
		if (!validate) value = '';
		elm.value = value;
  },

	setAllCaps: function(elm) {
		var value = elm.value;
    value = this.trim(value);
		//value = this.specialCharacterStrip(value);
		value = value.toUpperCase();
		//value = value.replace(/ /g,'_');
		//value = value.replace(/-/g,'_');
		elm.value = value;
	},
	
	specialCharacterStrip: function(value) {
		value = value.replace(/,/g,'');
		value = value.replace(/\./g,'');
		return value;
	},

  trim: function(value) {
    return value.replace(/^\s+/,'').replace(/\s+$/,'');
  },

  elfproef: function(elm) {
    var value = elm.value
    //Verwijder alle tekens die geen cijfers zijn
    value = value.replace(/\D/g,'');
    elm.value = value;
    var length = value.length;
    var som = 0;
    //Loop door de 9 cijfers met de 11 proef formule
    for (i=1; i<10; i++) {
      nr = value.charAt(i-1);
      som += nr * (10-i);
    } 
    //Geef resultaat van check terug (gironummers zijn 6 of 7 tekens, dus zou ook nog op gecontroleerd kunnen worden, is nu niet)
    if (som % 11 == 0 && length == 9) {
      return true
    } else {
      return false
    }
  },

  BSNCheck: function(elm) {
    var sofinr = elm.value.replace(/\D/g, '');
    elm.value = sofinr;
    sofinr = sofinr.toString();
    checksum = 0; 
    if(isNaN(sofinr) || sofinr.length!=9) { 
      //alert("Het BSN-/sofinummer is niet correct. Indien het eerste cijfer een 0 is van het BSN-/sofinummer, moet u deze ook invullen!"); 
      return false;
    } else { 
      for (i=0;i<8;i++) { 
        checksum += (sofinr.charAt(i)*(9-i)); 
      } 
      checksum -= sofinr.charAt(8); 
      if (checksum%11!=0) { 
        //alert("Het BSN/sofinummer is niet correct. Indien het eerste cijfer een 0 is van het BSN-/sofinummer, moet u deze ook invullen!"); 
        return false;
      } 
    } 
  },

  checkBeschikkingsnummer: function(elm) {
		var beschikkingsnr = this.trim(elm.value);
		beschikkingsnr = beschikkingsnr.toUpperCase();
    beschikkingsnr = this.specialCharacterStrip(beschikkingsnr);
    elm.value = beschikkingsnr;
    if (!beschikkingsnr.contains('T')) {
      alert('Het beschikkingsnummer klopt niet. Het nummer moet tenminste een T bevatten.');
      return false;
    } else {
      beschikkingsnr = beschikkingsnr.split('T');
      var sofinr = beschikkingsnr[0];
      sofinr = sofinr.replace(/\D/g, '');
      if (!this.checkBeschikkingsnummerBSNCheck(sofinr)) {
        alert('Het beschikkingsnummer klopt niet. De cijferreeks voor de T moet een kloppend BSN-/sofinummer zijn.');
        return false;
      } else
      {
        if (beschikkingsnr[1].substr(0,2) != '08') {
          alert('Het beschikkingsnummer klopt niet. De cijferreeks na de T moet \'08\' zijn.\r\nEr kunnen alleen formulieren van 2008 ingevuld worden.');
        } else
        {
          return true;
        }
      }
    }
  },

  checkBeschikkingsnummerBSNCheck: function(sofinr) {
    sofinr = sofinr.toString();
    checksum = 0; 
    if(isNaN(sofinr) || sofinr.length!=9) { 
      //alert("Het BSN-/sofinummer is niet correct. Indien het eerste cijfer een 0 is van het BSN-/sofinummer, moet u deze ook invullen!"); 
      return false;
    } else { 
      for (i=0;i<8;i++) { 
        checksum += (sofinr.charAt(i)*(9-i)); 
      } 
      checksum -= sofinr.charAt(8); 
      if (checksum%11!=0) { 
        //alert("Het BSN/sofinummer is niet correct. Indien het eerste cijfer een 0 is van het BSN-/sofinummer, moet u deze ook invullen!"); 
        return false;
      } 
      return true;
    } 
  },


	validateFilter: function(type, value) {
		return this.validators[type].test(value);
	},

	validators: {
		general:      /^[\.\:\,\;\*\(\!\?\'\)\/\\\$\%\&\+\-\_\#\'\@\w\d\s]+$/i, /* ' */
		alpha:        /^[a-z\s-_]+$/i, 
		email:        /^([a-z0-9_-]+)(\.[a-z0-9_-]+)*@([a-z0-9_-]+)(\.[a-z0-9_-]+)*[\.]([a-z0-9_-]+)$/i,
		captcha:      /^[\.\:\,\;\*\(\!\?\'\)\/\\\$\%\&\+\-\_\#\'\@\w\d\s]+$/i, /* ' */
		numeric:      /^\d+$/,
		alphanumeric: /^[a-z\d]+$/i,
 		postalcode:   /^([a-z]\d[a-z])[\s|-]?(\d[a-z]\d)$/i,
		zipcode:      /^\d{5}(-\d{4})?$/,
 		http:         /^((http|https|ftp):\/\/)?([a-z0-9_-]+)(\.[a-z0-9_-]+)+(\/\w+)*(\.[a-z0-9_-]+)*$/i,
		ipaddress:    /^(\d{1,3})(\.\d{1,3}){3}$/,
 		lzfulldate:   /^(0[1-9]|1[012])\/(0[1-9]|[12][0-9]|3[01])\/(?:18|19|20|21)\d\d$/,
		lzmonth:      /^(0[1-9]|1[012])$/,
		lzday:        /^(0[1-9]|[12][0-9]|3[01])$/,
		fulldate:     /^([1-9]|1[012])\/([1-9]|[12][0-9]|3[01])\/(?:18|19|20|21)\d\d$/,
		month:        /^([1-9]|1[012])$/,
		day:          /^([1-9]|[12][0-9]|3[01])$/,
		year:         /^\d{2}$/,
		fullYear:     /^(?:18|19|20|21)\d\d$/,
 		integer:      /^-?\d{1,3}(,?\d{3})*(\.00)?$/,
		float:        /^([0-9]\d*\.|0\.)[0-9]*\d+$/,
		currency:     /^(\$|\-|\$\-)?\d{1,3}([,]?\d{3})*(\.\d{2})?$/
	}
});