if ( !AI )
{
  alert('NAMESPACE AI indispensable');
}

/**
 * Constructeur
 *
 * @param {string} fId Identifiant HTML du formulaire à valider
 * @constructor
 * @public
 * @todo : passer en modèle objet AI.obj
 */
function CheckForm(fId)
{
  var F = $(fId);
  this.confirmer = false;
  this.fId = fId;
  this.champs = [];
  
  F._oldonsubmit = $(this.fId).onsubmit;
  F.instance = this;
  F.onsubmit = CheckForm._onsubmit;
  
  this.onBeforeValidate = function() { return []; };
  this.onAfterValidate = function() { return []; };

  // DIV indicateur de caractères
  CheckForm.$$I = $E('div', {}, {height:'3px', overflow:'hidden', backgroundColor:'white'});
  // DIV contenant l'indicateur de caractères
  CheckForm.$$C = document.body.appendChild( $E('div', { className:'cacher' }, { backgroundColor:'#C0C0C0', position:'absolute' }, [CheckForm.$$I] ) );
}

// cache des regex
CheckForm.RE_checkEmail = /^[\w\-][\w\-\.]+@[\w\-]+\.[a-zA-Z]{2,6}$/gi;

/**
 * Handler de soumission du formulaire
 * @param {event} e (evt) L'event de soumission
 * @private
 */
CheckForm._onsubmit = function(e)
{
  return CheckForm.__onsubmit.call(this.instance, e);
};

/**
 * Handler interne de soumission du formulaire
 *
 * Le scope d'application est l'instance de l'objet CheckForm
 *
 * @param {object} evt L'event de soumission
 * @private
 */
CheckForm.__onsubmit = function(evt)
{
  var formulaire = $(this.fId);
  if ( !formulaire )
  {
    alert('Formulaire introuvable');
    return true;
  }
  
  var errors = [];
  var firstErrorField = null;
  for ( var i=0, imax=this.champs.length; i<imax; i++ )
  {
    var v = this.champs[i].valider();
    if ( firstErrorField === null && v.length !== 0 )
    {
      firstErrorField = this.champs[i];
    }
    for ( var j=0, jmax=v.length; j<jmax; j++ )
    {
      errors.push(' - ' + v[j]);
    }
  }
  var errorBefore = this.onBeforeValidate();
  var errorAfter = this.onAfterValidate();
  if ( errors.length === 0 && errorBefore.length === 0 && errorAfter.length === 0)
  {
    if ( typeof $(this.fId)._oldonsubmit == 'function' )
    {
      return $(this.fId)._oldonsubmit(evt);
    }
    return true;
  }

  var msg = __('formulaire_non_soumis_suite_a_erreurs') + CR;
  if ( this.confirmer )
  {
    msg += __('confirmez_vous_soumission_formulaire');
  }
  else
  {
    msg += __('veuillez_corriger_formulaire');
  }
  msg += CR + CR;
  if ( errorBefore.length > 0 )
  {
    msg += errorBefore.join(CR) + CR;
  }
  msg += errors.join(CR);
  if ( errorAfter.length > 0 )
  {
    msg += CR + errorAfter.join(CR);
  }
  if ( this.confirmer )
  {
    if (confirm(msg))
    {
      var reussite = true;
      if ( typeof formulaire._oldonsubmit == 'function' )
      {
        reussite = formulaire._oldonsubmit(evt);
      }
      if ( reussite )
      {
        CheckForm.disableSubmit(formulaire);
      }
      return reussite;
    }
    else
    {
      if ( firstErrorField )
      {
        firstErrorField.focus();
      }
      return false;
    }
  }
  alert(msg);
  if ( firstErrorField )
  {
    firstErrorField.focus();
  }
  return false;
};

CheckForm.disableSubmit = function(frm)
{
  for ( var i=0, imax=frm.elements.length; i<imax; i++ )
  {
    frm.elements[i].disabled = true;
  }
};

CheckForm.prototype.addField = function(param)
{
  var champ = new Field(this.fId, param);
  if ( champ )
  {
    this.champs.push(champ);
  }
};

/**
 *
 * @private
 */
CheckForm.param = function(etat, obj, defaut)
{
  return typeof obj[etat] != 'undefined' ? obj[etat] : defaut;
};

function Field(fId, obj)
{
  if ( !obj.name )
  {
    return null;
  }

  var element = $(fId).elements[obj.name];
  if ( !element )
  {
    return null;
  }

  this.fId = fId;
  this.name = obj.name;
  this.required = CheckForm.param('required', obj, false);
  this.label = CheckForm.param('label', obj, obj.name.toLowerCase());
  this.type = element.type;
  this.CarTyp = CheckForm.param('CarTyp', obj, null);
  var value = this.getValue();
  this.defaultValue = value;
  this.lastValue = value;
  this.mini = CheckForm.param('mini', obj, null);
  this.maxi = CheckForm.param('maxi', obj, null);
  this.format = CheckForm.param('format', obj, null);
  this.errors = [];
  if ( 'CarCha' == this.CarTyp || 'CarUniCha' == this.CarTyp || 'CarTxt' == this.CarTyp || 'CarUniTxt'  == this.CarTyp )
  {
    element.maxi = this.maxi ? this.maxi : 65534;
    if ( !DOM.hasCSS(element, 'Xinha') )
    {
      element.$oldfocus = element.onfocus;
      element.$oldblur = element.onblur;
      element.$oldkeypress = element.onkeypress;
      element.onfocus = Field._onfocus;
      element.onblur = Field._onblur;
      element.onkeypress = Field._onkeypress;
    }
  }
  return this;
}

Field.prototype._getElement = function()
{
  return $(this.fId).elements[this.name];
};

/**
 * Place la barre d'indicateur de caractères
 * @param {HTMLElement} E (Element) L'élément textarea/input
 * @param {integer}     T (Top)     La position Top
 * @param {integer}     L (Left)    La position Left
 * @param (integer)     W (Width)   La taille
 * @param {boolean}     X (isXinha) true si c'est un éditeur Xinha, false si c'est un input/textarea standard
 */
Field._setIndicateurPos = function(E, T, L, W, X)
{
  var C = CheckForm.$$C;
//  C.style.top = DOM.pix(T, -3);
  if ( IS.IE )
  {
    C.style.top = DOM.pix(T);
  }
  else
  {
    C.style.top = DOM.pix(T, -3);
  }
//  C.style.top = DOM.pix( IS.IE ? T : T - 3);
  C.style.left = DOM.pix(L);
  C.style.width = DOM.pix(W);
  Field._synchroCaracs(E, W, X);
  DOM.show(C);
};

/**
 * Synchronize la barre d'indicateur de caractères
 * @param {HTMLElement} E (Element) Le textarea
 * @param {integer}     W (Width)   La taille
 * @param {boolean}     X (isXinha) true si c'est un éditeur Xinha, false si c'est un input/textarea standard
 * @private
 */
Field._synchroCaracs = function(E, W, X)
{
  var V = X === false ? E.value : 'contenu xinha';
  var I = CheckForm.$$I.style;
  var P = (V.length * 100 ) / E.maxi;
  var c = '#00FF80';
  if ( P >= 100 )
  {
    if ( X )
    {
      // resize le content xinha
    }
    else
    {
      E.value = V.substr(0, E.maxi);
    }
    P = 100;
    c = '#C40000';
  }
  else if ( P > 90 )
  {
    c = '#FF0000';
  }
  else if ( P > 75 )
  {
    c = '#FF8040';
  }
  else if ( P > 50 )
  {
    c = '#FFFF80';
  }
  I.width = intval(W * P / 100) + 'px';
  I.backgroundColor = c;
};

/**
 * Gestion du focus
 * @param {event} e (event) L'événement
 * @private
 */
Field._onfocus = function(e)
{
  if ( this.maxi > 0 )
  {
    Field._setIndicateurPos(this, DOM.getY(this), DOM.getX(this), this.offsetWidth, false);
  }
  if ( typeof this.$oldfocus == 'function' )
  {
    this.$oldfocus.call(this, e);
  }
};

/**
 * Gestion du blur
 * @param {event} e (event) L'événement
 * @private
 */
Field._onblur = function(e)
{
  DOM.hide(CheckForm.$$C);
  if ( typeof this.$oldblur == 'function' )
  {
    this.$oldblur.call(this, e);
  }
};

/**
 * Gestion du keypress
 * @param {event} e (event) L'événement
 * @private
 */
Field._onkeypress = function(e)
{
  Field._synchroCaracs(this, this.offsetWidth, false);
  if ( typeof this.$oldkeypress == 'function' )
  {
    this.$oldkeypress.call(this, e);
  }
};

/**
 * @private
 */
Field.prototype.valider = function()
{
  this.resetCSS();
  this.errors = [];
  if (typeof this['valider_' + this.CarTyp] !== 'undefined')
  {
    this['valider_' + this.CarTyp]();
  }
  else
  {
    alert('format inconnu : ' + this.CarTyp + '/' + this.name + '/' + this.label);
  }
  return this.errors;
};

Field.prototype.valider_CarBoo = function()
{
  var v = this.getValue();
  if ( v === '' && this.required)
  {
    this.errors.push(this.label + ' ' + __('est_obligatoire'));
    this.showErrorCSS('input_vide');
  }
};

Field.prototype.valider_CarBin = function()
{
  var v = this.getValue();
  if ( v === '' && this.required )
  {
    this.errors.push(this.label + ' ' + __('est_obligatoire'));
    this.showErrorCSS('input_vide');
  }
};

Field.prototype.valider_CarCha = function()
{
  var v = this.getValue();
  if ( v === '' )
  {
    if ( this.required )
    {
      this.errors.push(this.label + ' ' + __('est_obligatoire'));
      this.showErrorCSS('input_vide');
    }
  }
  else
  {
    if ( this.mini !== null && v.length < this.mini )
    {
      this.errors.push(this.label + ' ' + __('doit_avoir_caracteres_minimum') + ' ' + this.mini);
      this.showErrorCSS('input_incorrect');
    }
    if ( this.maxi !== null && v.length > this.maxi )
    {
      this.errors.push(this.label + ' ' + __('doit_avoir_caracteres_maximum') + ' ' + this.maxi);
      this.showErrorCSS('input_incorrect');
    }
    if (this.format == 'email')
    {
      if ( v.search(CheckForm.RE_checkEmail) )
      {
        this.errors.push(this.label + ' ' + __('est_pas_email_valide'));
        this.showErrorCSS('input_incorrect');
      }
    }
  }
};

Field.prototype.valider_CarDat = function()
{
  var v = this.getValue();
  if (v === '' && this.required )
  {
    this.errors.push(this.label + ' ' + __('est_obligatoire'));
    this.showErrorCSS('input_vide');
  }
};

Field.prototype.valider_CarFlo = function()
{
  var v = this.getValue();

  if ( v === '' )
  {
    if ( this.required )
    {
      this.errors.push(this.label + ' ' + __('est_obligatoire'));
      this.showErrorCSS('input_vide');
    }
  }
  else
  {
   if ( v === '*' ) { v = 1e+37; }
    if ( parseFloat(v) != v )
    {
      this.errors.push(this.label + ' ' + __('doit_etre_flottant'));
      this.showErrorCSS('input_incorrect');
    }
    v = parseFloat(v);
    if ( this.mini !== null && v < parseFloat(this.mini) )
    {
      this.errors.push(this.label + ' ' + __('doit_etre_superieur') + ' ' + this.mini);
      this.showErrorCSS('input_incorrect');
    }
    if ( this.maxi !== null && v > parseFloat(this.maxi) )
    {
      this.errors.push(this.label + ' ' + __('doit_etre_inferieur') + ' ' + this.maxi);
      this.showErrorCSS('input_incorrect');
    }
  }
};

Field.prototype.valider_CarInt = function()
{
  var v = this.getValue();
  if ( v === '' )
  {
    if ( this.required )
    {
      this.errors.push(this.label + ' ' + __('est_obligatoire'));
      this.showErrorCSS('input_vide');
    }
  }
  else
  {
   if ( v === '*' ) { v = 2147483647; }
    if ( parseInt(v, 10) != v )
    {
      this.errors.push(this.label + ' ' + __('doit_etre_entier'));
      this.showErrorCSS('input_incorrect');
    }
    if ( this.mini !== null && v < parseInt(this.mini, 10) )
    {
      this.errors.push(this.label + ' ' + __('doit_etre_superieur') + ' ' + this.mini);
      this.showErrorCSS('input_incorrect');
    }
    if ( this.maxi !== null && v > parseInt(this.maxi, 10) )
    {
      this.errors.push(this.label + ' ' + __('doit_etre_inferieur') + ' ' + this.maxi);
      this.showErrorCSS('input_incorrect');
    }
  }
};

Field.prototype.valider_CarObj = function()
{
  var v = this.getValue();
  if ( v === '' || parseInt(v, 10) === 0 || isNaN(parseInt(v, 10)) )
  {
    if ( this.required )
    {
      this.errors.push(this.label + ' ' + __('est_obligatoire'));
      this.showErrorCSS('input_vide');
    }
  }
};

Field.prototype.valider_CarTim = function()
{
  var v = this.getValue();
  if (v === '' && this.required )
  {
    this.errors.push(this.label + ' ' + __('est_obligatoire'));
    this.showErrorCSS('input_vide');
  }
};

Field.prototype.valider_CarTxt = function()
{
  var v = this.getValue();
  if ( this.format == 'WYSIWYG' )
  {
    v = v.stripTags();
  }
  if ( v === '' )
  {
    if ( this.required )
    {
      this.errors.push(this.label + ' ' + __('est_obligatoire'));
      this.showErrorCSS('input_vide');
    }
  }
  else
  {
    if ( this.mini !== null && v.length < this.mini )
    {
      this.errors.push(this.label + ' ' + __('doit_avoir_caracteres_minimum') + ' ' + this.mini);
      this.showErrorCSS('input_incorrect');
    }
    if ( this.maxi !== null && v.length > this.maxi )
    {
      this.errors.push(this.label + ' ' + __('doit_avoir_caracteres_maximum') + ' ' + this.maxi);
      this.showErrorCSS('input_incorrect');
    }
  }
};

Field.prototype.resetCSS = function()
{
  var elt = this._getElement();
  DOM.removeCSS(elt, 'input_vide');
  DOM.removeCSS(elt, 'input_incorrect');
};

Field.prototype.showErrorCSS = function(css)
{
  var elt = this._getElement();
  this.resetCSS();
  DOM.addCSS(elt, css);
};

Field.prototype.focus = function() {
  var elt = this._getElement();
  var old_autocomplete = elt.autocomplete;
  elt.autocomplete = 'off';
  // elt.setAttribute("autocomplete", "off");
  elt.focus();
  if ( old_autocomplete )
  {
    elt.autocomplete = old_autocomplete;
    // elt.setAttribute("autocomplete", old_autocomplete);
  }
};

Field.prototype.getValue = function ()
{
  var type = (this.type.substring(0,6) == "select") ? "select" : this.type;
  var value = [];
  var elt = this._getElement();

  if ( type == "select" )
  {
    if ( this.type == "select-one" )
    {
      value.push((elt.selectedIndex == -1) ? "" : elt.options[elt.selectedIndex].value);
    }
    else
    {
      for ( var i=0, imax=elt.length; i<imax; i++ )
      {
        if ( elt[i].selected )
        {
          value.push(elt.options[i].value.trim());
        }
      }
    }
  }
  else if ( type == "checkbox" || type == "radio" )
  {
    // if more then one checkbox
    if( !!elt[0] && !elt.value.trim() )
    {
      for ( var j=0, jmax=elt.length; j<jmax; j++ )
      {
        if ( elt.options[j].checked )
        {
          value.push(elt.options[j].value.trim());
        }
      }
    }
    else if ( elt.checked )
    {
      value.push(elt.value.trim());
    }
  }
  else
  {
    value.push(elt.value.trim());
  }
  return value.join('§').trim();
};
