/***********************************************************
****  Elimina espaços do início e do fim do argumento.  ****
***********************************************************/

function trim(str) {
//   var ini, fim;
//
//   for (ini = 0; (ini < str.length && str[ini] == ' '); ini++);
//   for (fim = str.length - 1; (fim >= 0 && str[fim] == ' '); fim--);
//
//   return str.substr(ini, fim - ini + 1);
   return (str.replace(/^\s+/, '').replace(/\s+$/, ''));
}


/*********************************************************
****  Elimina caracteres não-numéricos do argumento.  ****
*********************************************************/

function onlyNumbers(str) {
//   var i;
//   var newStr = '';
//
//   for (i = 0; i < str.length; i++) {
//      newStr += ((str.charAt(i) < '0' || str.charAt(i) > '9') ? '' : str.charAt(i));
//   }
//
//   return newStr;
   return (str.replace(/\D/g, ''));
}


/*********************************************************
****  Valida a data informada (1o. argumento) de      ****
****  acordo com o formato desejado (2o. argumento).  ****
*********************************************************/

function isDate(strDate, strFmt) {
   var reDate;
   var y, m, d;
   var dateParts, year, month, day;


   function isLeapYear(y) {
      return (y % 4 != 0) ? false : (y % 100 != 0) ? true : (y % 400 != 0) ? false : true;
   }

   strFmt = strFmt || 'ymd';

   switch (strFmt.toLowerCase()) {
      case 'ymd' :
         reDate = /^(\d{4})\/(\d{2})\/(\d{2})$/;
         y = 1; m = 2; d = 3;
         break;
      case 'dmy' :
         reDate = /^(\d{2})\/(\d{2})\/(\d{4})$/;
         y = 3; m = 2; d = 1;
         break;
      case 'mdy' :
         reDate = /^(\d{2})\/(\d{2})\/(\d{4})$/;
         y = 3; m = 1; d = 2;
         break;
      default:
         return false;
   }

   if (!reDate.test(strDate)) return false;

   dateParts = reDate.exec(strDate);
   year  = parseInt(dateParts[y], 10);
   month = parseInt(dateParts[m], 10);
   day   = parseInt(dateParts[d], 10);

   if (day < 1) return false;

   switch (parseInt(month)) {
      case 1 :
      case 3 :
      case 5 :
      case 7 :
      case 8 :
      case 10:
      case 12:
         if (day > 31) return false;
         break;
      case 4 :
      case 6 :
      case 9 :
      case 11:
         if (day > 30) return false;
         break;
      case 2 :
         if (day > (isLeapYear(year) ? 29 : 28)) return false;
         break;
      default:
         return false;
   }

   if (year < 1900) return false;

   return true;
}


/*************************************************
****  Passa a data informada (1o. argumento)  ****
****  do primeiro para o segundo formato.     ****
*************************************************/

function changeFormat(strDate, fromFormat, toFormat) {
   var reDate, y, m, d;
   var dateParts, year, month, day;
   var newDate;


   fromFormat = fromFormat || 'ymd';
   toFormat   = toFormat   || 'ymd';

   switch (fromFormat.toLowerCase()) {
      case 'ymd' :
         reDate = /^(\d{4})\/(\d{2})\/(\d{2})$/;
         y = 1; m = 2; d = 3;
         break;
      case 'dmy' :
         reDate = /^(\d{2})\/(\d{2})\/(\d{4})$/;
         y = 3; m = 2; d = 1;
         break;
      case 'mdy' :
         reDate = /^(\d{2})\/(\d{2})\/(\d{4})$/;
         y = 3; m = 1; d = 2;
         break;
      default:
         return '';
   }

   if (!reDate.test(strDate)) return '';

   dateParts = reDate.exec(strDate);

   switch (toFormat.toLowerCase()) {
      case 'ymd' :
         newDate = dateParts[y] + '/' + dateParts[m] + '/' + dateParts[d];
         break;
      case 'dmy' :
         newDate = dateParts[d] + '/' + dateParts[m] + '/' + dateParts[y];
         break;
      case 'mdy' :
         newDate = dateParts[m] + '/' + dateParts[d] + '/' + dateParts[y];
         break;
      default:
         return '';
   }

   return newDate;
}


/**********************************
****  Valida o CPF informado.  ****
**********************************/

function validaCPF(CPF) {

   if (trim(CPF) == '') {
      alert('CPF inválido.');
      return false;
   }

   /*
   ** Elimina qualquer caractere não-numérico.
   */
   CPF = onlyNumbers(CPF);

   if (CPF == '') {
      alert('CPF inválido.');
      return false;
   }
   

   /*
   ** Acrescenta zeros suficientes para completar 11 dígitos.
   */
   for (;CPF.length < 11;) {
      CPF = '0' + CPF;
   }

   if (CPF == '00000000000') {
      alert('CPF inválido.');
      return false;
   }

   /*
   ** Retorna se o argumento não tiver apenas 11 dígitos.
   */
   if (CPF.length != 11) {
      alert('CPF inválido. Ele deve ter apenas 11 dígitos.');
      return false;
   }



   if (!validaDV(CPF, 9)) {
      alert('O penúltimo dígito do seu CPF está incorreto. Certifique-se de tê-lo informado corretamente.');
      return false;
   }

   if (!validaDV(CPF, 10)) {
      alert('O último dígito do seu CPF está incorreto. Certifique-se de tê-lo informado corretamente.');
      return false;
   }

   return true;
}


/*******************************************************
****  Valida o dígito verificador do CPF informado  ****
****  de acordo com o segundo argumento.            ****
*******************************************************/

function validaDV(dvCPF, dvLimite) {
   /*
   ** Cálculo de dígito verificador.
   */
   var dvDigito = 0;
   var dvFator = dvLimite + 1;
   var dvSoma = 0;

   for (var i = 0; i < dvLimite; i++) {
      dvSoma = dvSoma + (parseInt(dvCPF.charAt(i), 10) * dvFator);
      dvFator--;
   }

   dvDigito = dvSoma % 11;
   if (dvDigito < 2) {
      dvDigito =  0;
   } else {
      dvDigito = 11 - dvDigito;
   }

   /*
   ** Teste do dígito verificador.
   */
   if (dvDigito != parseInt(dvCPF.charAt(dvLimite), 10)) {return false;}

   return true;
}


/*************************************************************************************
****  V1.1.1:    Sandeep V. Tamhankar (stamhankar@hotmail.com)                    ****
****  Original:  Sandeep V. Tamhankar (stamhankar@hotmail.com)                    ****
****  Changes:                                                                    ****
****  1.1.1: Removed restriction that countries must be preceded by a domain,     ****
****         so abc@host.uk is now legal.  However, there's still the             ****
****         restriction that an address must end in a two or three letter word.  ****
****  1.1:   Rewrote most of the function to conform more closely to RFC 822.     ****
****  1.0:   Original                                                             ****
*************************************************************************************/

function emailCheck (emailStr) {
   /*
   ** The following pattern is used to check if the entered e-mail address
   ** fits the user@domain format.  It also is used to separate the username
   ** from the domain.
   */
   var emailPat = /^(.+)@(.+)$/;

   /*
   ** The following string represents the pattern for matching all special
   ** characters.  We don't want to allow special characters in the address. 
   ** These characters include ( ) < > @ , ; : \ " . [ ]
   */
   var specialChars = '\\(\\)<>@,;:\\\\\\\"\\.\\[\\]';

   /*
   ** The following string represents the range of characters allowed in a 
   ** username or domainname.  It really states which chars aren't allowed.
   */
   var validChars = '\[^\\s' + specialChars + '\]';

   /*
   ** The following pattern represents the range of characters allowed as
   ** the first character in a valid username or domain.  I just made it
   ** the same as above, but if you want to add a different constraint,
   ** you would change it here.
   */
   var firstChars = validChars;

   /*
   ** The following pattern applies if the "user" is a quoted string (in
   ** which case, there are no rules about which characters are allowed
   ** and which aren't; anything goes).  E.g. "jiminy cricket"@disney.com
   ** is a legal e-mail address.
   */
   var quotedUser = '(\"[^\"]*\")';

   /*
   ** The following pattern applies for domains that are IP addresses,
   ** rather than symbolic names.  E.g. joe@[123.124.233.4] is a legal
   ** e-mail address. NOTE: The square brackets are required.
   */
   var ipDomainPat = /^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;

   /*
   ** The following string represents at atom (basically a series of
   ** non-special characters.)
   */
   var atom = '(' + firstChars + validChars + '*' + ')';

   /*
   ** The following string represents one word in the typical username.
   ** For example, in john.doe@somewhere.com, john and doe are words.
   ** Basically, a word is either an atom or quoted string.
   */
   var word = '(' + atom + '|' + quotedUser + ')';

   /*
   ** The following pattern describes the structure of the user.
   */
   var userPat = new RegExp('^' + word + '(\\.' + word + ')*$');

   /*
   ** The following pattern describes the structure of a normal symbolic
   ** domain, as opposed to ipDomainPat, shown above.
   */
   var domainPat = new RegExp('^' + atom + '(\\.' + atom + ')*$');




   /********************************************************************************
   ** Finally, let's start trying to figure out if the supplied address is valid. **
   ********************************************************************************/

   var errStr;

   /*
   ** Begin with the course pattern to simply break up user@domain into
   ** different pieces that are easy to analyze.
   */
   var matchArray = emailStr.match(emailPat);
   if (matchArray == null) {
      /*
      ** Too many/few @'s or something; basically, this address doesn't
      ** even fit the general mould of a valid e-mail address.
      */
      errStr = "Email address seems incorrect (check @ and .'s)";
      return false;
   }

   var user   = matchArray[1];
   var domain = matchArray[2];



   // See if "user" is valid
   if (user.match(userPat) == null) {
      // User is not valid
      errStr = "The username doesn't seem to be valid.";
      return false;
   }

   /*
   ** If the e-mail address is at an IP address (as opposed to a symbolic
   ** host name) make sure the IP address is valid.
   */
   var IPArray = domain.match(ipDomainPat);
   if (IPArray != null) {
      // this is an IP address
      for (var i = 1; i <= 4; i++) {
         if (IPArray[i] > 255) {
            errStr = "Destination IP address is invalid!";
            return false;
         }
      }
      return true;
   }

   // Domain is symbolic name
   var domainArray = domain.match(domainPat);
   if (domainArray == null) {
      errStr = "The domain name doesn't seem to be valid.";
      return false;
   }


   /*
   ** Domain name seems valid, but now make sure that it ends in a
   ** three-letter word (like com, edu, gov) or a two-letter word,
   ** representing country (uk, nl), and that there's a hostname preceding 
   ** the domain or country.
   */

   /*
   ** Now we need to break up the domain to get a count of how many atoms
   ** it consists of.
   */
   var atomPat = new RegExp(atom, 'g');
   var domArr  = domain.match(atomPat);
   var len     = domArr.length;

   for (var i = 0; i < domArr.length; i++) {
      if (!isNaN(domArr[i])) {
         errStr = "The atom " + domArr[i] + " is a number. So the whole address should be ";
         errStr += "an IP address and be enclosed in square brackets.";
         return false;
      }
   }

   if ((domArr[domArr.length-1].length < 2) || (domArr[domArr.length-1].length > 3)) {
      // The address must end in a two letter or three letter word.
      errStr = "The address must end in a three-letter domain, or two letter country.";
      return false;
   }

   // Make sure there's a host name preceding the domain.
   if (len < 2) {
      errStr = "This address is missing a hostname!";
      return false;
   }

   // If we've gotten this far, everything's valid!
   return true;
}
