//LIBRERIA DE FUNCIONES DE VALIDACION
//Actualizada en Mayo 2002 para validaci� de tarjetas de cr�ito (QD)
//Junio 2002. Funci� para mensaje personalizado en checkFill: checkFillwMsg (SEP)
//Junio 2002. Funciones para checkBox
//Junio 2002. Validaci� de fechas tipo MySQL (QD)

var defaultEmptyOK = false;
var whitespace = " \t\n\r";				// caracteres de espacios en blanco
var decimalPointDelimiter = ".";			// caracter delimitador decimal

//AVISO DE ERROR
var mPrefix = "No se introdujo ningn valor en el campo '"
var mSuffix = "'.  Es un campo requerido. Por favor introduzcalo ahora."

//AVISOS DE ERROR
var iEmail = "Este campo debe ser una direccion de correo electr�ico v�ida (nombre@servidor.com). Por favor ingr�ela ahora."
var iInt = "Este campo debe de ser un nmero entero positivo"
var iDesc = "Este campo debe ser un nmero entero o decimal entre 0 y 100 \n Puede dejarlo en blanco para aplicar valores predeterminados"
var iFloat = "Este campo debe ser un nmero entero o decimal positivo"
var iEmpty ="es requerido"
var iMySQLDate = "Este campo debe ser una fecha num�ica v�ida en formato 'aaaa-mm-dd' ej. 1997-08-29";

//INFORMACIONES DEL STATUS VAR
var pEntryPrompt = "Por favor introduzca "
var pEmail = "una direccion valida de e-mail (ej. nombre@servidor.com)."
var pEdad = "la edad (ej. 15, 20) "
var pDesc = "el descuento que se aplicar�(ej. 12.5)  Deje en blanco para aplicar descuento predeterminado. "

//FUNCIONES DE VALIDACION GENERAL

function isEmpty(s)
{   return ((s == null) || (s.length == 0))
}

function isDigit (c)
{   return ((c >= "0") && (c <= "9"))
}

// Returns true if string s is empty or 
// whitespace characters only.

function isWhitespace (s)

{   var i;

    // Is s empty?
    if (isEmpty(s)) return true;

    // Search through string's characters one by one
    // until we find a non-whitespace character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);

        if (whitespace.indexOf(c) == -1) return false;
    }

    // All characters are whitespace.
    return true;
}

function isInteger (s)

{   var i;

    if (isEmpty(s)) 
       if (isInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isInteger.arguments[1] == true);

    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number.
        var c = s.charAt(i);

        if (!isDigit(c)) return false;
    }

    // All characters are numbers.
    return true;
}

function isSignedInteger (s)

{   if (isEmpty(s)) 
       if (isSignedInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isSignedInteger.arguments[1] == true);

    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedInteger.arguments.length > 1)
            secondArg = isSignedInteger.arguments[1];

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
           startPos = 1;    
        return (isInteger(s.substring(startPos, s.length), secondArg))
    }
}

function isPositiveInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isPositiveInteger.arguments.length > 1)
        secondArg = isPositiveInteger.arguments[1];

    // The next line is a bit byzantine.  What it means is:
    // a) s must be a signed integer, AND
    // b) one of the following must be true:
    //    i)  s is empty and we are supposed to return true for
    //        empty strings
    //    ii) this is a positive, not negative, number

    return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (parseInt (s) > 0) ) );
}

function isNonnegativeInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isNonnegativeInteger.arguments.length > 1)
        secondArg = isNonnegativeInteger.arguments[1];

      return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (parseInt (s) >= 0) ) );
}


function isFloat (s)

{   var i;
    var seenDecimalPoint = false;

    if (isEmpty(s)) 
       if (isFloat.arguments.length == 1) return defaultEmptyOK;
       else return (isFloat.arguments[1] == true);

    if (s == decimalPointDelimiter) return false;

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number.
        var c = s.charAt(i);

        if ((c == decimalPointDelimiter) && !seenDecimalPoint) seenDecimalPoint = true;
        else if (!isDigit(c)) return false;
    }

    // All characters are numbers.
    return true;
}


function isEmail (s)
{   if (isEmpty(s)) 
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);
   
    // is s whitespace?
    if (isWhitespace(s)) return false;
    
    var i = 1;
    var sLength = s.length;

    // look for @
    while ((i < sLength) && (s.charAt(i) != "@"))
    { i++
    }

    if ((i >= sLength) || (s.charAt(i) != "@")) return false;
    else i += 2;

    // look for .
    while ((i < sLength) && (s.charAt(i) != "."))
    { i++
    }

    // there must be at least one character after the .
    if ((i >= sLength - 1) || (s.charAt(i) != ".")) return false;
    else return true;
}


function checkEmail (theField, emptyOK)
{   if (checkEmail.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else if (!isEmail(theField.value, false)) 
       return warnInvalid (theField, iEmail);
    else return true;
}


/* FUNCTIONS TO NOTIFY USER OF INPUT REQUIREMENTS OR MISTAKES. */


// Display prompt string s in status bar.

function prompt (s)
{   window.status = s
}

// Display data entry prompt string s in status bar.

function promptEntry (s)
{   window.status = pEntryPrompt + s
}

function warnEmpty (theField, s)
{   theField.focus()
    alert(mPrefix + s + mSuffix)
    return false
}


function warnInvalid (theField, s)
{   theField.focus()
    theField.select()
    alert(s)
    return false
}


function checkEmail (theField, emptyOK)
{   if (checkEmail.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else if (!isEmail(theField.value, false)) 
       return warnInvalid (theField, iEmail);
    else return true;
}

//Validacion de enteros positivos

function checkInt (theField, emptyOK)
{   if (checkInt.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if (!isNonnegativeInteger(theField.value, false)) 
       return warnInvalid (theField, iInt);
    else return true;
}

//Validaci� de numeros decimales entre 0 y 1

function checkDesc (theField, emptyOK)
{   if (checkDesc.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if (!isFloat(theField.value, false)) 
       return warnInvalid (theField, iDesc);
   else 
    if ( ((theField.value)< 0) || ((theField.value) >= 99) )
       return warnInvalid (theField, iDesc);
    else return true;
}

//Validaci� de nmeros de punto flotante positivos (dineros, descuentos grandes etc...)

function checkFloat (theField, emptyOK)
{   if (checkFloat.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if (!isFloat(theField.value, false)) 
       return warnInvalid (theField, iFloat);
       else return true;
}

//Calcula si el a� es o no bisiesto
function isLeap(year) { 
	if (year%4==0 && ((year%100!=0) || (year%400==0))) return true; else return false; 
}

//Obtiene el numero de d�s del mes del a� especificado Ene=1..Dic=12
function daysOfMonth(month,year){
	var Months = new Array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	if(month == 2) {//Febreros 
		if(isLeap(year)) return 29;	else return 28;
	}
	else { //Cualquier mes distinto de febrero
		return Months[month];
	}
}

function isMySQLDate (dateValue) {
	//Crear un arreglo con el valor del campo
	var dateString = dateValue.toString();
	var expStr = dateString.split("-");
	
	//Convertir a enteros los elementos del arreglo
	var year = parseInt(expStr[0],10);
	var month = parseInt(expStr[1],10);
	var day = parseInt(expStr[2],10);
	
	//Revisar que los valores sean enteros v�idos	
	if((year>0)&&(month>0)&&(day>0)){
		if((year<1900)||(year>2100)||(month>12)){
			return false;	
		}
		else {
			if(day > daysOfMonth(month,year)) {
				return false; 	
			}
			else {
				return true;
			}
		}
	}
	else { 
		return false;	
	}
}

function checkMySQLDate (theField, emptyOK) {
	//Aceptar o no valores nulos
	if(checkMySQLDate.arguments.length == 1) emptyOK = defaultEmptyOK;
	if((emptyOK == true) && (isEmpty(theField.value))) return true;

	if(!isMySQLDate(theField.value)){
		return warnInvalid(theField, iMySQLDate);
	}
	
	else return true;
}


//Verificaci� unicamente de llenado de casilla

function checkFill (theField) {
if (isWhitespace(theField.value))
	return warnEmpty (theField, theField.name)
else return true;

}

function checkFillwMsg (theField,theMsg) {
if (isWhitespace(theField.value)) {
	theField.focus()
    alert(theMsg)
	return false;
}	
else return true;

}

// funciones de validacion del registro
function comparePassword(password1,password2) {
	if (password1 != password2) {
		alert("Las contraseñas no coinciden/\nPasswords doesn't match");
		return false;
	}
	
	return true;
}

function checkValidUsername(username) {
    for( var i = 0; i < username.length; ++i ) {		// make sure the number is all digits.. (by design)
    	var c = username.charAt(i);

    	if (!(( c >= '0' && c <= '9' ) || 
    		( c >= 'a' && c <= 'z' ) || 
    		( c >= 'A' && c <= 'Z' ) )) {
    		alert("Usuario invalido: Por favor introduzca solo letras y numeros/\nInvalid username: Please use only letters and digits, do not use spaces or hyphens.");
        	return false;
        }
	}		
}

// Funciones para validacion de tarjeta de credito
/*
There are three functions in this set for credit card validation.
The main function is:
validateCard(cardNumber,cardType,cardMonth,cardYear)
	parameters:
		all paramaters are string values.
		Month & Year come from the select input fields in the form, so they are defined.
		cardType can be:
			'a' for American Express
			'd' for Discover
			'm' for MasterCard
			'v' for Visa
	description:
		this function will check string length, valid characters, specific credit card prefixes and test
		the Mod 10 (LUHN Formula) for validating possible credit card numbers. this function can only
		authorize that the given card data is potentially valid. You would still need to run actual
		card validation routines to verify the actual account.
	returns:
		this function returns true if the card number could be valid for the card type and expiration date.
		false otherwise.	

supporting functions:
mod10( cardNumber )
	parameters:
		this function takes the text string card number and runs the Mod 10 formula on its respective digits.
	description:
		Mod 10 is the check digit formula for the supported cards these functions attempt to validate.
	returns:
		this function returns true if the number passes the check digit test.
		false otherwise.
expired( cardMonth, cardYear )
	parameters:
		this function takes the text string values given by the html form.
	description:
		this function basically will check to make sure todays date is less than the expiration date the user inputs.
		this function is not locked into using 2 digit dates.
	returns:
		this fucntion returns true if the card is expired.
		false otherwise.
*/
function mod10( cardNumber ) { // LUHN Formula for validation of credit card numbers.
	
	var ar = new Array( cardNumber.length );
	var i = 0,sum = 0;


	for( i = 0; i < cardNumber.length; ++i ) {
		ar[i] = parseInt(cardNumber.charAt(i));
	}
	for( i = ar.length -2; i >= 0; i-=2 ) { // you have to start from the right, and work back.
		ar[i] *= 2;							 // every second digit starting with the right most (check digit)
		if( ar[i] > 9 ) ar[i]-=9;			 // will be doubled, and summed with the skipped digits.
	}										 // if the double digit is > 9, ADD those individual digits together 


    	for( i = 0; i < ar.length; ++i ) {
    		sum += ar[i];						 // if the sum is divisible by 10 mod10 succeeds
    	}
    	return (((sum%10)==0)?true:false);	 	
}


function isExpired( month, year ) {

	var now = new Date();							// this function is designed to be Y2K compliant.
	var expiresIn = new Date(year,month,0,0,0);		// create an expired on date object with valid thru expiration date

    expiresIn.setMonth(expiresIn.getMonth()+1);		// adjust the month, to first day, hour, minute & second of expired month
    if( now.getTime() < expiresIn.getTime() ) return false;
    return true;									// then we get the miliseconds, and do a long integer comparison
}

function checkAll(forma) {
	trueFalse = true;
	for (i = 0; i < forma.length; i++) {
    	forma.elements[i].checked = trueFalse; 
   	}
}

function invertAll(forma) {
	for (i = 0; i < forma.length; i++) {
    	forma.elements[i].checked = !forma.elements[i].checked ; 
   	}
}

function validateCard(cardNumber,cardType,cardMonth,cardYear) {

	if( cardNumber.length == 0 ) {						//most of these checks are self explanitory
    	//alert("Por favor introduzca un numero valido de tarjeta de credito/\nPlease enter a valid card number.");
    	// si no se captura numero de tarjeta esta bien
        return true;				
    }

    for( var i = 0; i < cardNumber.length; ++i ) {		// make sure the number is all digits.. (by design)
    	var c = cardNumber.charAt(i);

    	if( c < '0' || c > '9' ) {
    		alert("Por favor introduzca solo numeros, sin espacios ni guiones/\nPlease enter a valid card number. Use only digits. do not use spaces or hyphens.");
        	return false;
        }
	}
    
    var length = cardNumber.length;			//perform card specific length and prefix tests


    switch( cardType ) {
    	case 'AmericanExpress':
			if( length != 15 ) {
				alert("Por favor introduzca un numero valido de tarjeta American Express/\nPlease enter a valid American Express Card number.");
				return false;
            }
            var prefix = parseInt( cardNumber.substring(0,2));


			if( prefix != 34 && prefix != 37 ) {
				alert("Por favor introduzca un numero valido de tarjeta American Express/\nPlease enter a valid American Express Card number.");
				return false;
			}
			break;

		case 'd':

			if( length != 16 ) {
				alert("Por favor introduzca un numero valido de tarjeta Discover/\nPlease enter a valid Discover Card number.");
				return false;
			}
			var prefix = parseInt( cardNumber.substring(0,4));
	
			if( prefix != 6011 ) {
				alert("Por favor introduzca un numero valido de tarjeta Discover/\nPlease enter a valid Discover Card number.");
				return false;
			}
			break;
    
		case 'MasterCard':

			if( length != 16 ) {
				alert("Por favor introduzca un numero valido de tarjeta MasterCard/\nPlease enter a valid MasterCard number.");
				return false;
			}
			var prefix = parseInt( cardNumber.substring(0,2));

			if( prefix < 51 || prefix > 55) {
				alert("Por favor introduzca un numero valido de tarjeta MasterCard/\nPlease enter a valid MasterCard Card number.");
				return false;
			}
			break;

		case 'VISA':

			if( length != 16 && length != 13 ) {
				alert("Por favor introduzca un numero valido de tarjeta VISA/\nPlease enter a valid Visa Card number.");
				return false;
			}
			var prefix = parseInt( cardNumber.substring(0,1));

			if( prefix != 4 ) {
				alert("Por favor introduzca un numero valido de tarjeta VISA/\nPlease enter a valid Visa Card number.");
				return false;
			}
			break;
	}
	if( !mod10( cardNumber ) ) { 		// run the check digit algorithm
		alert("El numero de tarjeta de credito es invalido/\nThis is not a valid credit card number.");
		return false;
	}
	if( isExpired( cardMonth, cardYear ) ) {							// check if entered date is already expired.
		alert("Tarjeta de credito expirada/\nThe expiration date you have entered would make this card invalid.");
		return false;
	}
	
	return true; // at this point card has not been proven to be invalid
}
