//# TODO: remove comments and "fluff characters" before release
//#
//#--------------------------------------------------------------------
//# validate_credit_card
//#
//#    This function is based on a similar function by: 
//#        Brett Error (brett@interwebdesign.com) 
//#        mcmer (webmaster@artconcept.at) 
//# 
//#    The method of validation is based on the Luhn check
//#        (see http://www.beachnet.com/~hstiles/cardtype.html)
//#
//#  Arguments: 
//#     credit_card_number: MUST BE A STRING VALUE.  INTEGER AND
//#                         FLOAT PRECISION NOT GREAT ENOUGH 
//#                         TO HANDLE CREDIT CARD NUMBERS!!! 
//#     card_type:         Accepted types are "American Express", 
//#                        "Mastercard", "Visa" and "Discover"
//#     expr_month:        The month the card expires (1 - 12).  This
//#                        argument is optional.
//#     expr_year:         The year the card expires (1999 - 2020).  This
//#                        argument is optional unless expr_month is
//#                        provided.
//#  returns:   
//#     0: valid
//#     1: invalid card type
//#     2: invalid card number
//#     3: invalid expiration date
//#     4: card expired
//#     5: invalid args (or unfulfilled arg requirements)
//#--------------------------------------------------------------------
function validate_credit_card (credit_card_number, credit_card_type, expr_month, expr_year ) 
{      

	// alert ("entering validate_credit_card, parms are:\n\tcredit_card_number = "+
	//         credit_card_number+
	//         "\n\tcredit_card_type = "+credit_card_type+
	//         "\n\texpr_month = "+expr_month+
	//         "\n\texpr_year = "+expr_year);

	if( !credit_card_number || (credit_card_number.length == 0) || 
	    !credit_card_type || (credit_card_type.length == 0) )
	{
		return( 5 );
	}
	
  //# Clean out any non-numeric characters in credit_card_number 
  //credit_card_number.replace (/[^0-9]/g, '');

  //# REMOVE ANY NON DIGITS
 	tmpcard = new String(credit_card_number);
	len = tmpcard.length;
	cnt = 0;
	hold = '';	

	while(cnt < len)
	{	
		c = tmpcard.charAt(cnt);
		if(c.match(/[0-9]/))
		{
			if(hold == ''){ hold = c; }
			else { hold += c; }
		}
		cnt++;
	}
	if(hold != ''){ credit_card_number = hold; }
 //# FINISHED REMOVING NON DIGITS

	
  ccn_length = credit_card_number.length; 
	card_type = credit_card_type.toLowerCase();

//alert("Card Number = "+credit_card_number+"\nCard Lenght = "+ccn_length+"\nCard Type = "+card_type);

  switch( card_type )
  {
    case "american express":
        if( !credit_card_number.match(/^3[4|7]/) || ccn_length != 15 )
        {
          return( 2 );
        }
        break;

    case "discover":
        if( (ccn_length != 16) || (credit_card_number.substr(0, 4) != '6011') )
        {
          return( 2 );
        }
        break;

    case "master card":
        if( !credit_card_number.match(/^5[1-5]/) || ccn_length != 16 )
        {
          return( 2 );
        }
        break;

    case "visa":
        if( !credit_card_number.match(/^4/) || (ccn_length != 13 && ccn_length != 16) )
        {
          return( 2 );
        }
        break;

    default:
       return( 1 );
  }

  //# Now, validate the number using the Luhn check

  //# Reverse the credit card number
	xx = new Array();
	ii = 0;
	for( nn = (credit_card_number.length-1); nn >= 0; nn-- )
	{
		xx[ii++] = credit_card_number[nn];
	}

  //# Loop through the reversed credit card number one digit at a time. Transform odd
  //# numbered entries and sum with even entries
  sum = 0;
	for( i = 0;  ii < ccn_length ; ii++ )
  {
    //# This formula is equivalent to multiplying a number by two and then, if the result has two digits, summing the two digits.
    if( ii % 2 )  //# Test to see if the current string index ( ii ) is odd.
    {
      sum += ( ( xx[ ii ] % 5 ) * 2 ) + Math.floor( ( xx[ ii ] / 5 ) );
    }
    else
    {
      sum += xx[ ii ];
    }
  }

  //# if the result, divided by 10 has a fractional remainer, then the card # is invalid.
  if( sum % 10 )
  {
    return( 2 );
  }
	
  //# now check for valid date if a date was passed in
  if( (expr_month != 0) || (expr_year != 0) )
  {
    //# values for month or year were entered.  Validate them.
    if( !((expr_month >= 1) && (expr_month <= 12)) )
    {
			return( 3 );
		}
		if( !((expr_year >= 1998) && (expr_year <= 2020)) )
		{
			return( 3 );
		}

		currdate = new Date();
		curr_month = currdate.getMonth()+1;
		curr_year  = currdate.getFullYear();

		if( (parseInt(expr_year)*100 + parseInt(expr_month)) < (curr_year*100 + curr_month) )
		{
			return( 4 );
		}
	}
	
	return( 0 );
}  


