/**************************************************************\
          Scripts de comprobación genéricos.
          ==================================

   El objetivo de esta biblioteca es aunar las comprobaciones
de javascript para que sean mas sencillas de mantener en un
futuro.

\**************************************************************/



/*
FUNCION es_email
================

Devuelve si el email introducido está bien formado o si no lo
está. Admite una lista de emails separados por comas.

Actualmente soporta los nombres de dominio:
   - Dos letras (para no poner todos los posibles paises)
   - .com
   - .net
   - .org
   - .mil
   - .int
   - .edu
   - .biz
   - .info
   - .name
   - .gov

FUNCION es_email
=================



*/

function es_email(v){
   var limpio, a_emails, ok, idx_emails;
   idx_emails=0;
   a_emails=v.split(",");
   while((idx_emails<a_emails.length)&&(ok=_es_email(_trim(a_emails[idx_emails++]))));
   return ok;
}

function _es_email(v){
   var t=/^(\w|\~)(\w|\~|\.|\-)*@(\w|\~)(\w|\~|\.|\-)*\.(([A-Za-z]{2})|([bB][iI][zZ])|([Ii][Nn][Ff][Oo])|([Cc][Oo][Mm])|([Nn][Ee][Tt])|([Oo][Rr][Gg])|([Mm][Ii][Ll])|([Ii][Nn][Tt])|([Ee][Dd][Uu])|([nN][aA][mM][eE])|[gG][oO][vV])$/
   return t.test(v);
}

function _trim(v){
   return v.replace(/^( )*([^ ]*)( )*$/,"$2");
}

/*

FUNCION es_moneda
=================

Devuelve verdad si la cadena pasada es del estilo moneda.
Está limitado a cantidades menores de 1000 millones

*/

function es_moneda(v){
   var t=/^\d{1,9}(\.(\d{1,2})?)?$/
   return t.test(v);
}

/*

FUNCION es_telefono
=================

Devuelve verdad si el telefono es aparentemente válido para Colombia

*/

function es_telefono(v){
   var t=/^(0|1|2|3|4|5|6|7|8|9)\d{6,12}$/
   return t.test(v);
}

/*

FUNCION es_cp
=================

Devuelve verdad si el código postal es aparentemente válido para Colombia

*/

function es_cp(v){
   var t=/^(([0-4]\d{4})|(5[0-2]\d{3}))$/
   return t.test(v);
}

/*

FUNCION es_letra
=================

Devuelve verdad si se ha pasado una letra diferente a la ñ

*/

function es_letra(v){
   var t=/^([A-Z]|[a-z])$/
   return t.test(v);
}

/*

FUNCION es_entero
=================

Devuelve verdad si se ha pasado un entero mayor que cero

*/

function es_entero(v){
   var t=/^[1-9]\d*$/
   return t.test(v);
}

/*

FUNCION es_dni
==============

Devuelve verdad si se ha pasado una cadena con forma de dni (nif) español

*/

function es_dni(dni){
   var forma_dni = /^\d{1,8}[a-zA-Z]$/
   var letras = 'TRWAGMYFPDXBNJZSQVHLCKE';

   if(!forma_dni.test(dni)){
      return es_nie(dni);
   }

   var numero = dni.substring(0,dni.length-1);
   var letra  = dni.substring(dni.length-1);

   return (letra.toUpperCase() == letras.substr(numero%23,1));
}

function es_nie(dni){
   var forma_nie = /^[xX]\d{1,8}[a-zA-Z]$/
   var letras = 'TRWAGMYFPDXBNJZSQVHLCKE';

   if(!forma_nie.test(dni)){
      return false;
   }

   var numero = dni.substring(1,dni.length-1);
   var letra  = dni.substring(dni.length-1);

   return (letra.toUpperCase() == letras.substr(numero%23,1));
}

/*
FUNCION es_texto
================

Devuelve verdad si una cadena es de texto

*/

function es_texto(texto){
   var t = /^([àèìòùÀÈÌÒÙáéíóúÁÉÍÓÚäëïöüÄËÏÖÜçÇa-zA-ZñÑ]|\s)*[àèìòùÀÈÌÒÙáéíóúÁÉÍÓÚäëïöüÄËÏÖÜçÇa-zA-ZñÑ]([àèìòùÀÈÌÒÙáéíóúÁÉÍÓÚäëïöüÄËÏÖÜçÇa-zA-ZñÑ]|\s)*$/
   return t.test(texto);
}

/*
FUNCTION es_fecha
=================

Devuelve verdad si la combinación de día, mes y año son correctas

*/

/** Funcion auxiliar. Si hacemos un parseInt de 08 o 09 no funciona porque evalua que son octales y devuelve 0!!!!! */
function _to_int(str){
   var t=/^(0)*(\d+)$/
   if(!t.test(str)) return 0;
   a_v=t.exec(str);
   return parseInt(a_v[2]);
}

function es_fecha(dia, mes, ano){
   var idia=_to_int(dia), imes=_to_int(mes), iano=_to_int(ano);

   if(!idia||!imes||!iano) return false;

   switch(imes){
      case 1:
      case 3:
      case 5:
      case 7:
      case 8:
      case 10:
      case 12:
         return (idia<=31);
      case 4:
      case 6:
      case 9:
      case 11:
         return (idia<=30);
      case 2:
         return (idia<=(28+((((!(iano%4))&&(iano%100))||!(iano%400))?1:0)));
   }
   return false;
}


/*
FUNCTION es_cuenta_corriente
============================

Devuelve verdad si los parámetros pasados conforman un número de cuenta corriente válido

*/
function es_cuenta_corriente(s_entidad, s_oficina, s_control, s_cuenta){
   var es_entidad = /^\d{4}$/;
   var es_oficina = /^\d{4}$/;
   var es_control = /^\d{2}$/;
   var es_cuenta  = /^\d{10}$/;

   if(!es_entidad.test(s_entidad) ||
      !es_oficina.test(s_oficina) ||
      !es_control.test(s_control) ||
      !es_cuenta.test(s_cuenta)) return false;

   var primer_digito = parseInt(s_oficina.charAt(3)) *  6 +
                       parseInt(s_oficina.charAt(2)) *  3 +
                       parseInt(s_oficina.charAt(1)) *  7 +
                       parseInt(s_oficina.charAt(0)) *  9 +
                       parseInt(s_entidad.charAt(3)) * 10 +
                       parseInt(s_entidad.charAt(2)) *  5 +
                       parseInt(s_entidad.charAt(1)) *  8 +
                       parseInt(s_entidad.charAt(0)) *  4;
   primer_digito %= 11;
   primer_digito  = 11 - primer_digito;
   if(primer_digito == 10) primer_digito = 1; else
   if(primer_digito == 11) primer_digito = 0;

   var segundo_digito = parseInt(s_cuenta.charAt(9)) *  6 +
                        parseInt(s_cuenta.charAt(8)) *  3 +
                        parseInt(s_cuenta.charAt(7)) *  7 +
                        parseInt(s_cuenta.charAt(6)) *  9 +
                        parseInt(s_cuenta.charAt(5)) * 10 +
                        parseInt(s_cuenta.charAt(4)) *  5 +
                        parseInt(s_cuenta.charAt(3)) *  8 +
                        parseInt(s_cuenta.charAt(2)) *  4 +
                        parseInt(s_cuenta.charAt(1)) *  2 +
                        parseInt(s_cuenta.charAt(0)) *  1;
   segundo_digito %= 11;
   segundo_digito  = 11 - segundo_digito;
   if(segundo_digito == 10) segundo_digito = 1; else
   if(segundo_digito == 11) segundo_digito = 0;

   var s_control_datos = primer_digito + '' + segundo_digito;

   return(s_control_datos == s_control);
}


/*
FUNCTION es_tipo_tarjeta_credito
================================

Devuelve verdad si el número de tarjeta pasada corresponde con el tipo indicado.
Los posibles tipos son:
   0: Visa
   1: American Express
   2: Master Card
   3: Discover
   4: Diners Club
*/
function es_tipo_tarjeta_credito(tipo, s_numero_tarjeta){
   var t = /^\d{13,16}$/;
   if(!t.test(s_numero_tarjeta)) return false;

   switch(tipo){
      case 0: // Visa
         return (s_numero_tarjeta.length    == 16 || s_numero_tarjeta.length == 13) &&
                (s_numero_tarjeta.charAt(0) == '4');
      case 1: // American Express
         return (s_numero_tarjeta.length    == 15)  &&
                (s_numero_tarjeta.charAt(0) == '3') &&
                (/^(4|7)$/.test(s_numero_tarjeta.charAt(1)));
      case 2: // Master Card
         return (s_numero_tarjeta.length    == 16)  &&
                (s_numero_tarjeta.charAt(0) == '5') &&
                (/^[1-5]$/.test(s_numero_tarjeta.charAt(1)));

      case 3: // Discover
         return (s_numero_tarjeta.length == 16) &&
                (s_numero_tarjeta.substring(0,4) == "6011");
      case 4: // Diners club
         return (s_numero_tarjeta.length    == 14)  &&
                (s_numero_tarjeta.charAt(0) == '3') &&
                (/^(0|6|8)$/.test(s_numero_tarjeta.charAt(1)));
      default:
         return false;
   }
}

/*
FUNCTION es_tarjeta_credito
===========================

Devuelve verdad si el número de tarjeta pasado es válido
*/
function es_tarjeta_credito(s_numero_tarjeta){
   var t = /^\d{13,16}$/;
   if(!t.test(s_numero_tarjeta)) return false;

   var suma = 0, parcial, i;

   for (i=0; i<s_numero_tarjeta.length; i++) {
      parcial = parseInt(s_numero_tarjeta.charAt(s_numero_tarjeta.length - 1 - i)) * ((i % 2) + 1);
      suma   += (parcial<10)?parcial:(parcial % 10) + 1;
   }
   return ((suma % 10) == 0);
}

