 /*FormValidator                                                       *
 *                                                                     *
 * Copyright (C) 2005-2006                                             *
 * Author: David Bernard <dwayneb@users.sf.net>                        *
 * Based on (copy fragment of):                                        *
 *  * YAV - Yet Another Validator  v1.3.0                              *
 *    Author: Federico Crivellaro <f.crivellaro@gmail.com>             *
 *    WWW: http://yav.sourceforge.net                                  *
 *    License: LGPL 2.1                                                *
 * Dependencies :                                                      *
 *  * MochiKit v1.3.1                                                  *
 *    Author: Bob Ippolito                                             *
 *    WWW: http://mochikit.com                                         *
 *    License: MIT License, or the Academic Free License version 2.1   *
 *                                                                     *
 * This library is free software; you can redistribute it and/or       *
 * modify it under the terms of the GNU Lesser General Public          *
 * License as published by the Free Software Foundation; either        *
 * version 2.1 of the License, or (at your option) any later version.  *
 *                                                                     *
 * This library is distributed in the hope that it will be useful,     *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   *
 * Lesser General Public License for more details.                     *
 *                                                                     *
 * You should have received a copy of the GNU Lesser General Public    *
 * License along with this library; if not, write to the Free Software *
 * Foundation, Inc.,59 Temple Place,Suite 330,Boston,MA 02111-1307 USA *
 *                                                                     *
 * last revision:  21 SEP 2006                                         *
 * patch : Christian Menapace (22/01/2007)                             *
 *         DATE-FORMAT was dd-MM-yyyy now dd/mm/yyyy, because line 374 *
 *         wait mm for the month pattern.                              *
 /**********************************************************************/

if (typeof(MochiKit) == 'undefined') {
  throw "FormValidator depends on MochiKit";
}

/*
==============================================================
  String Extension
==============================================================
*/
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, ''); };

/*
==============================================================
  Field Helper
==============================================================
*/
Field = {
  labelOf : function(fieldId) {
    var labelEls = MochiKit.DOM.getElementsByTagAndClassName('label');
    for(i in labelEls) {
      var el = labelEls[i];
      if (MochiKit.DOM.getNodeAttribute(el, 'for') == fieldId) {
        label = MochiKit.DOM.scrapeText(el);
        label = label.replace(/(:|\*|\s)+$/, '');
        label = label.trim();
        return label;
      }
    }
    return fieldId;
  },

  find : function(fieldId) {
    var elem = MochiKit.DOM.getElement(fieldId);
    if (MochiKit.Base.isUndefinedOrNull(elem)) {
      throw "field not found : " + fieldId;
    }
    if (MochiKit.Base.isUndefinedOrNull(elem.type)) {
      log("search on :" + elem);
      var inputs = MochiKit.DOM.getElementsByTagAndClassName('INPUT', null, elem);
      if (inputs.length < 1) {
        throw "field not found : " + fieldId;
      }
      elem = inputs[0];
      forEach(inputs, function(item) {
        if ((fieldId == item.id) || (fieldId == item.name)) {
        log("is checkedo :" + item.checked);
          if (item.checked) {
            elem = item;
         }
        }
      });
    }
    return elem;
  }
};
/*
==============================================================
  AlertCollector
==============================================================
*/
AlertCollector = function(inErrorClassName) {
  if (MochiKit.Base.isUndefinedOrNull(inErrorClassName)) {
    inErrorClassName = "inputError";
  }
  this._inErrorClassName = inErrorClassName;
  this._alerts = {};
  return this;
};

AlertCollector.prototype = {
  reset : function() {
    var ids = MochiKit.Base.keys(this._alerts);
    for(i in ids) {
      var id = ids[i];
      try {
        MochiKit.DOM.removeElementClass(id, this._inErrorClassName);
      } catch(exc) {
        MochiKit.Logging.logWarning("can't remove class to '" + id + "' ... " + exc);
      }
    }
    this._alerts = {};
  },

  add : function(field, message) {
    var key = field.id;
    if (MochiKit.Base.isUndefinedOrNull(key) || key == '') {
      key = field.name;
    }
    var list = this._alerts[key];
    if (MochiKit.Base.isUndefinedOrNull(list)) {
      list = [];
      this._alerts[key] = list;
    }
    list.push(message);
  },

  displayPopup : function() {
    var str = '';
    var ids = MochiKit.Base.keys(this._alerts);
    for(i in ids) {
      var id = ids[i];
      str += Field.labelOf(id) + ' :\n';
          for (j in this._alerts[id]) {
              str += '  - ' + this._alerts[id][j] + '\n';
          }
    }
      if (ids.length > 0) {
        str = HEADER_MSG + str + FOOTER_MSG;
      alert(str);
    }
  },

  displayOnClass : function(fieldId) {
    if (MochiKit.Base.isUndefinedOrNull(fieldId)) {
      var ids = MochiKit.Base.keys(this._alerts);
      for(i in ids) {
        this.displayOnClass(ids[i]);
      }
    } else {
      try {
        MochiKit.DOM.addElementClass(fieldId, this._inErrorClassName);
      } catch(exc) {
        MochiKit.Logging.logWarning("can't add class to '" + fieldId + "' ... " + exc);
      }
    }
  },

  display : function(fieldId) {
    this.displayOnClass(fieldId);
    this.displayPopup();
  }
};

/*
==============================================================
  FormValidator
==============================================================
*/
FormValidator = {
  _defaultAlertCollector : new AlertCollector(),

  __repr__ : function () {
      return "[FormValidator 0.1]";
  },

  toString : function () {
      return this.__repr__();
  },

  getField : function(rule) {
    return Field.find(rule.fieldId);
  },

  getFieldx2 : function(rule) {
    return [Field.find(rule.fieldId), Field.find(rule.fieldId2)];
  },

  getMessage : function(rule, defaultMsg, arg2, arg3) {
    var msg = ''+defaultMsg;
    if (!MochiKit.Base.isUndefinedOrNull(rule.msg)) {
      msg = rule.msg;
    }
    msg = msg.replace('{1}', Field.labelOf(rule.fieldId));
    msg = msg.replace('{2}', arg2);
    msg = msg.replace('{3}', arg3);
    log("msg :" + msg);
    return msg;
  },

  checkddMMyyyy : function(dd, MM, yyyy) {
      var back = true;
      if (    (dd > 31) || (MM > 12) ||
            (dd==31 && (MM==2 || MM==4 || MM==6 || MM==9 || MM==11) ) ||
            (dd >29 && MM==2) ||
            (dd==29 && (MM==2) && ((yyyy%4 > 0) || (yyyy%4==0 && yyyy%100==0 && yyyy%400>0 )) )) {
       back = false;
      }
      return back;
  },

  performChecks : function(rules, collector /*optinal*/) {
    try {
      var back = true;
      if (MochiKit.Base.isUndefinedOrNull(collector)) {
          collector = this._defaultAlertCollector;
      }
      collector.reset();
      if (MochiKit.Base.isArrayLike(rules)) {
          for(i in rules) {
              back = rules[i].check(collector, rules[i]) && back;
          }
      } else if (MochiKit.Base.isUndefinedOrNull(rules.check)) {
          back = rules.check(collector, rules) && back;
      }
      collector.display();
      log("checks result " + back);
      return back;
    } catch(exc) {
      MochiKit.Logging.logFatal(exc);
      alert(exc);
      return false;
      //throw exc;
    }
  },

  isNotEmpty : function(alertCollector, rule) {
      var field = FormValidator.getField(rule);
      var isEmpty = true;
      switch(field.type.toLowerCase()) {
          case 'text':
          case 'password':
          case 'textarea':
              isEmpty =  (field.value.trim() == '');
              break;
          case 'radio':
          case 'checkbox':
              isEmpty = (!field.checked);
              break;
          case 'select':
              isEmpty = (!field.selectedIndex && (field.selectedIndex == 0));
              break;
      }
      if (isEmpty) {
          alertCollector.add(field, FormValidator.getMessage(rule, REQUIRED_MSG));
          return false;
      }
      return true;
  },

  isNotZero : function(alertCollector, rule) {
      rule.pattern = "^([1-9]{1,1})*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = NOTZERO_MSG;
      }
      return FormValidator.matchPattern(alertCollector, rule);
  },

  matchPattern : function(alertCollector, rule) {
      var field = FormValidator.getField(rule);
      if (field.value.trim() == '') {
        return true;
      }
      var pattern = rule.pattern;
      if (MochiKit.Base.isUndefinedOrNull(pattern)) {
          return true;
      }
      if (pattern.charAt(0) != '^') {
        pattern = '^'+pattern
    }
    if (pattern.charAt(pattern.length - 1) != '$') {
      pattern = pattern + '$'
    }
      log("check pattern " + pattern);
      // only for text and textarea
      reg = new RegExp(pattern); // /pattern/
      if (!reg.test(field.value)) {
          alertCollector.add(field, FormValidator.getMessage(rule, REGEXP_MSG, pattern));
          return false;
      }
      return true;
  },

  isEmail : function(alertCollector, rule) {
    rule.pattern = "^(([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}){0,1}$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = EMAIL_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isTelephone : function(alertCollector, rule) {
    rule.pattern = "^0[1-68][0-9]{8}$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = TELEPHONE_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isNumeric : function(alertCollector, rule) {
    rule.pattern = "^[0-9]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = NUMERIC_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isInteger : function(alertCollector, rule) {
    rule.pattern = "^[-+]{0,1}[0-9]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = INTEGER_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isDouble : function(alertCollector, rule) {
    rule.pattern = "^[-+]{0,1}[0-9]*[" + DECIMAL_SEP + "]{0,1}[0-9]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = DOUBLE_MSG;
      }
    if (FormValidator.matchPattern(alertCollector, rule)) {
      var field = FormValidator.getField(rule);
      separator = field.value.indexOf(',',0);
      if (separator > 0) {
      	field.value = field.value.substring(0, separator) + "." + field.value.substring(separator+1);
      }
      return true;
    } else {
    	return false;
    }
  },

  isAlphabetic : function(alertCollector, rule) {
    rule.pattern = "^[A-Za-z]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = ALPHABETIC_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isAlphaNumeric : function(alertCollector, rule) {
    rule.pattern = "^[A-Za-z0-9]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = ALPHANUMERIC_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isAlNumHyphen : function(alertCollector, rule) {
    rule.pattern = "^[A-Za-z0-9\-_]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = ALNUMHYPHEN_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isAlNumHyphenAt : function(alertCollector, rule) {
    rule.pattern = "^[A-Za-z0-9\-_@]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = ALNUMHYPHENAT_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isAlphaspace : function(alertCollector, rule) {
    rule.pattern = "^[A-Za-z0-9\-_ \n\r\t]*$";
      if (MochiKit.Base.isUndefinedOrNull(rule.msg)) {
          rule.msg = ALPHASPACE_MSG;
      }
    return FormValidator.matchPattern(alertCollector, rule);
  },

  isDate : function(alertCollector, rule) {
      var field = FormValidator.getField(rule);
      if (field.value.trim() == '') {
        return true;
      }
      var pattern = rule.pattern;
      if (MochiKit.Base.isUndefinedOrNull(pattern)) {
          pattern = DATE_FORMAT;
      }
      pattern = pattern.toLowerCase();
      var ddStart = pattern.indexOf('dd');
      var mmStart = pattern.indexOf('mm');
      var yyyyStart = pattern.indexOf('yyyy');
      if ((ddStart < 0) || (mmStart < 0) || (yyyyStart < 0)) {
          throw "bad configuration for DATE_FORMAT : "+pattern;
      }
      firstslash = field.value.indexOf('/',0);
      if (firstslash < 0) {
          alertCollector.add(field, FormValidator.getMessage(rule, DATE_MSG, pattern));
          return false;
	  }
      dd   = field.value.substring(0, firstslash);
      if (dd.charAt(0)=='0') { dd = dd.substring(1, 10); } else { dd = dd.substring(0, 10); }
      if (dd.charAt(0)=='0') { dd = dd.substring(1, 10); } else { dd = dd.substring(0, 10); }
      if (dd.charAt(0)=='0') { dd = dd.substring(1, 10); } else { dd = dd.substring(0, 10); }

      secondslash = field.value.indexOf('/',firstslash+1);
      if (secondslash < 0) {
          alertCollector.add(field, FormValidator.getMessage(rule, DATE_MSG, pattern));
          return false;
	  }
      mm   = field.value.substring(firstslash+1, secondslash);
      if (mm.charAt(0)=='0') { mm = mm.substring(1, 10); } else { mm = mm.substring(0, 10); }
      if (mm.charAt(0)=='0') { mm = mm.substring(1, 10); } else { mm = mm.substring(0, 10); }
      if (mm.charAt(0)=='0') { mm = mm.substring(1, 10); } else { mm = mm.substring(0, 10); }

      yyyy = field.value.substring(secondslash+1, 10);
      if (dd*1 < 10) { field.value = '0'+ dd + "/"; }
      else         { field.value =      dd + "/"; }
      if (mm*1 < 10) { field.value = field.value + '0'+ mm + '/'; }
      else         { field.value = field.value      + mm + '/'; }

      if (yyyy.charAt(0)=='0') { yyyy = yyyy.substring(1, 10); } else { yyyy = yyyy.substring(0, 10); }
      if (yyyy.charAt(0)=='0') { yyyy = yyyy.substring(1, 10); } else { yyyy = yyyy.substring(0, 10); }
      if (yyyy.charAt(0)=='0') { yyyy = yyyy.substring(1, 10); } else { yyyy = yyyy.substring(0, 10); }
      if (yyyy.charAt(0)=='0') { yyyy = yyyy.substring(1, 10); } else { yyyy = yyyy.substring(0, 10); }
      if      (yyyy*1 == 0)  { field.value = field.value + '2000' + yyyy; }
      else if (yyyy*1 < 10)  { field.value = field.value + '200' + yyyy; }
      else if (yyyy*1 < 30)  { field.value = field.value + '20' + yyyy; }
      else if (yyyy*1 <= 99) { field.value = field.value + '19' + yyyy; }
      else                   { field.value = field.value + yyyy; }

      strReg = pattern.replace('dd','([0-3]+[0-9])').replace('mm','([0-1]+[0-9])').replace('yyyy','([0-9]{4})');
      reg = new RegExp("^" + strReg + "$");
      if (!reg.test(field.value)) {
          alertCollector.add(field, FormValidator.getMessage(rule, DATE_MSG, pattern));
          return false;
      }
      dd   = field.value.substring(ddStart, ddStart+2);
      MM   = field.value.substring(mmStart, mmStart+2);
      yyyy = field.value.substring(yyyyStart, yyyyStart+4);
      if ( !FormValidator.checkddMMyyyy(dd, MM, yyyy) ) {
          alertCollector.add(field, FormValidator.getMessage(rule, DATE_MSG, pattern));
          return false;
      }
      return true;
  },

  hasMinLength : function(alertCollector, rule) {
      var field = FormValidator.getField(rule);
      if (field.value.trim() == '') {
        return true;
      }
      var minLength = rule.minLength;
      if (!MochiKit.Base.isUndefinedOrNull(minLength) && (field.value.length < minLength)) {
          alertCollector.add(field, FormValidator.getMessage(rule, MINLENGTH_MSG, minLength));
          return false;
      }
      return true;
  },

  hasMaxLength : function(alertCollector, rule) {
      var field = FormValidator.getField(rule);
      var maxLength = rule.maxLength;
      if (!MochiKit.Base.isUndefinedOrNull(maxLength) && (field.value.length > maxLength)) {
          alertCollector.add(field, FormValidator.getMessage(rule, MAXLENGTH_MSG, maxLength));
          return false;
      }
      return true;
  },

  isEqualTo : function(alertCollector, rule) {
      var fields = FormValidator.getFieldx2(rule);
      var minLength = rule.minLength;
      if (fields[0].value != fields[1].value) {
          alertCollector.add(fields[0], FormValidator.getMessage(rule, EQUAL_MSG, Field.labelOf(fields[1].id)));
          return false;
      }
      return true;
  },

  alwaysFailed : function(alertCollector, rule) {
    MochiKit.Logging.logWarning("FormValidator.alwaysFailed() requested");
    alert("FormValidator.alwaysFailed() requested");
    return false;
  }
};
/*
==============================================================
  FormValidator Configuration
==============================================================
*/

// change these to set your own decimal separator and your date format
DECIMAL_SEP =',.';
THOUSAND_SEP = '';
DATE_FORMAT = 'dd/mm/yyyy';

// change these strings for your own translation (do not change {n} values!)
TELEPHONE_MSG ='{1} is not a valid value.Character allowed: 0123456789';

HEADER_MSG = 'Error data entry:\n';
FOOTER_MSG = 'Please try again.';
DEFAULT_MSG = 'Some values are not valid.';
REQUIRED_MSG = '{1} is required.';
ALPHABETIC_MSG = '{1} n\'est pas une valeur valable. Caractères permis: A-Za-z';
ALPHANUMERIC_MSG = '{1} n\'est pas une valeur valable. Caractères permis: A-Za-z0-9';
ALNUMHYPHEN_MSG = '{1} n\'est pas une valeur valable. Caractères permis: A-Za-z0-9\-_';
ALNUMHYPHENAT_MSG = '{1} n\'est pas une valeur valable. Caractères permis: A-Za-z0-9\-_@';
ALPHASPACE_MSG = '{1} n\'est pas une valeur valable. Caractères permis: A-Za-z0-9\-_espace';
MINLENGTH_MSG = '{1} doit comporter au moins {2} character.';
MAXLENGTH_MSG = '{1} must be at most {2} caractères.';
NUMRANGE_MSG = '{1} doit être un nombre compris dans cet intervalle: {2}.';
DATE_MSG = '{1} is invalide date. Required format: {2}.';
NUMERIC_MSG = '{1} must be a number.';
NOTZERO_MSG = '{1} doit être différent de zéro.';
INTEGER_MSG = '{1} doit être un nombre entier.';
DOUBLE_MSG = '{1} doit être un nombre décimal.';
REGEXP_MSG = '{1} n\'est pas une valeur valable. Format requis: {2}.';
EQUAL_MSG = '{1} doit être égal à {2}.';
NOTEQUAL_MSG = '{1} ne doit pas être égal à {2}.';
DATE_LT_MSG = '{1} doit précéder cette date: {2}.';
DATE_LE_MSG = '{1} doit précéder ou être égal à cette date: {2}.';
EMAIL_MSG = '{1} must be a valid email address.';
EMPTY_MSG = '{1} should be empty.';


CONF_DATE_MSG = '{2} est un format de date invalide.';