CardType = {

	init : function() {
		//Start the credit cards validador Objects
		CardType.Cards = new CardType.makeArray(4);
		CardType.Cards[0] = new CardType.constructor("MasterCard", "51,52,53,54,55", "16");
		CardType.MasterCard = CardType.Cards[0];
		
		CardType.Cards[1] = new CardType.constructor("VisaCard", "4", "13,16");
		CardType.VisaCard = CardType.Cards[1];
		
		CardType.Cards[2] = new CardType.constructor("AmExCard", "34,37", "15");
		CardType.AmExCard = CardType.Cards[2];
		
		CardType.Cards[3] = new CardType.constructor("DinersClubCard", "30,36,38", "14");
		CardType.DinersClubCard = CardType.Cards[3];
		/*
		CardType.Cards[4] = new CardType.constructor("DiscoverCard", "6011", "16");
		CardType.DiscoverCard =CardType.Cards[4];
		
		CardType.Cards[5] = new CardType.constructor("enRouteCard", "2014,2149", "15");
		CardType.enRouteCard = CardType.Cards[5];
		
		CardType.Cards[6] = new CardType.constructor("JCBCard","3088,3096,3112,3158,3337,3528,3529,353,354,355,356,357,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3566,3540,3541", "16");
		CardType.JCBCard = CardType.Cards[6];
		*/
		CardType.LuhnCheckSum = CardType.Cards[4] = new CardType.constructor();
	},
	
	constructor : function() {
			var n;
			var argv = this.constructor.arguments;
			var argc = this.constructor.arguments.length;
			
			this.objname = "object CardType";
			
			var tmpcardtype = (argc > 0) ? argv[0] : "CardObject";
			var tmprules = (argc > 1) ? argv[1] : "0,1,2,3,4,5,6,7,8,9";
			var tmplen = (argc > 2) ? argv[2] : "13,14,15,16,19";
			
			// set CardNumber method.
			this.setCardNumber = CardType.setCardNumber;
			
			// setCardType method.
			this.setCardType = CardType.setCardType;
			
			// setLen method.
			this.setLen = CardType.setLen;
			
			// setRules method.
			this.setRules = CardType.setRules;
			
			// setExpiryDate method.
			this.setExpiryDate = CardType.setExpiryDate;
			
			this.setCardType(tmpcardtype);
			this.setLen(tmplen);
			this.setRules(tmprules);
			if (argc > 4)
			this.setExpiryDate(argv[3], argv[4]);
			
			// checkCardNumber method.
			this.checkCardNumber = CardType.checkCardNumber;
			
			// getExpiryDate method.
			this.getExpiryDate = CardType.getExpiryDate;
			
			// getCardType method.
			this.getCardType = CardType.getCardType;
			
			// isCardNumber method.
			this.isCardNumber = CardType.isCardNumber;
			
			// isExpiryDate method.
			this.isExpiryDate = CardType.isExpiryDate;
			
			// luhnCheck method.
			this.luhnCheck = CardType.luhnCheck;
			
			return this;
	},
		
	
		/*************************************************************************\
		   boolean checkCardNumber([String cardnumber, int year, int month])
		   return true if cardnumber pass the luhncheck and the expiry date is
		   valid, else return false.
		\*************************************************************************/
		checkCardNumber : function() {
		 
		  var argv = this.checkCardNumber.arguments;
		  var argc = this.checkCardNumber.arguments.length;
		  
		  var cardnumber = (argc > 0) ? argv[0] : this.cardnumber;
		  var year = (argc > 1) ? argv[1] : this.year;
		  var month = (argc > 2) ? argv[2] : this.month;

		  this.setCardNumber(cardnumber);
		  this.setExpiryDate(year, month);
		
		  if (!this.isCardNumber()) {
			return false;
		  }
		  /*
		  if (!this.isExpiryDate()) {
			return false;
		  }*/
		  return true;
		},
		
		/*************************************************************************\
		   String getCardType()
		   return the cardtype.
		\*************************************************************************/
		 getCardType : function() {
		  return this.cardtype;
		},
		
		/*************************************************************************\
		   String getExpiryDate()
		   return the expiry date.
		\*************************************************************************/
		 getExpiryDate : function() {
		  return this.month + "/" + this.year;
		},
		
		/*************************************************************************\
		   boolean isCardNumber([String cardnumber])
		   return true if cardnumber pass the luhncheck and the rules, else return
		   false.
		\*************************************************************************/
		 isCardNumber : function() {
		  var argv = this.isCardNumber.arguments;
		  var argc = this.isCardNumber.arguments.length;
		  var cardnumber = (argc > 0) ? argv[0] : this.cardnumber;
		  if (!this.luhnCheck())
			return false;
		
		  for (var n = 0; n < this.len.size; n++)
			if (cardnumber.toString().length == this.len[n]) {
			  for (var m = 0; m < this.rules.size; m++) {
				var headdigit = cardnumber.substring(0, this.rules[m].toString().length);
				if (headdigit == this.rules[m])
				  return true;
			  }
			  return false;
			}
		
		  return false;
		},
		
		/*************************************************************************\
		  boolean isExpiryDate([int year, int month])
		  return true if the date is a valid expiry date,
		  else return false.
		\*************************************************************************/
		 isExpiryDate : function() {
		  var argv = this.isExpiryDate.arguments;
		  var argc = this.isExpiryDate.arguments.length;
		
		  year = argc > 0 ? argv[0] : this.year;
		  month = argc > 1 ? argv[1] : this.month;
		
		  if (!CardType.isNum(year+""))
			return false;
		  if (!CardType.isNum(month+""))
			return false;
		  today = new Date();
		  expiry = new Date(year, month);
		  if (today.getTime() > expiry.getTime())
			return false;
		  else
			return true;
		},
		
		/*************************************************************************\
		  boolean isNum(String argvalue)
		  return true if argvalue contains only numeric characters,
		  else return false.
		\*************************************************************************/
		 isNum : function(argvalue) {
		 
		  var argvalue = argvalue.toString();
		
		  if (argvalue.length == 0)
			return false;
		
		  for (var n = 0; n < argvalue.length; n++)
			if (argvalue.substring(n, n+1) < "0" || argvalue.substring(n, n+1) > "9")
			  return false;
		
		  return true;
		},
		
		/*************************************************************************\
		  boolean luhnCheck([String CardNumber])
		  return true if CardNumber pass the luhn check else return false.
		  Reference: http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl
		\*************************************************************************/
		 luhnCheck : function() {
		  var argv = this.luhnCheck.arguments;
		  var argc = this.luhnCheck.arguments.length;
		
		  var CardNumber = argc > 0 ? argv[0] : this.cardnumber;
		
		  if (! CardType.isNum(CardNumber)) {
			return false;
		  }
		
		  var no_digit = CardNumber.length;
		  var oddoeven = no_digit & 1;
		  var sum = 0;
		
		  for (var count = 0; count < no_digit; count++) {
			var digit = parseInt(CardNumber.charAt(count));
			if (!((count & 1) ^ oddoeven)) {
			  digit *= 2;
			  if (digit > 9)
			digit -= 9;
			}
			sum += digit;
		  }
		  if (sum % 10 == 0) {
			return true;
		  }else{
			return false;
		  }
		},
		
		/*************************************************************************\
		  ArrayObject makeArray(int size)
		  return the array object in the size specified.
		\*************************************************************************/
		 makeArray : function(size) {
		  this.size = size;
		  return this;
		},
		
		/*************************************************************************\
		   CardType setCardNumber(cardnumber)
		   return the CardType object.
		\*************************************************************************/
		 setCardNumber : function(cardnumber) {
		  this.cardnumber = cardnumber;
		  return this;
		},
		
		/*************************************************************************\
		   CardType setCardType(cardtype)
		   return the CardType object.
		\*************************************************************************/
		 setCardType : function(cardtype) {
		  this.cardtype = cardtype;
		  return this;
		},
		
		/*************************************************************************\
		   CardType setExpiryDate(year, month)
		   return the CardType object.
		\*************************************************************************/
		 setExpiryDate : function(year, month) {
		  this.year = year;
		  this.month = month;
		  return this;
		},
		
		/*************************************************************************\
		   CardType setLen(len)
		   return the CardType object.
		\*************************************************************************/
		 setLen : function(len) {
		  // Create the len array.
		  if (len.length == 0 || len == null)
			len = "13,14,15,16,19";
		
		  var tmplen = len;
		  n = 1;
		  while (tmplen.indexOf(",") != -1) {
			tmplen = tmplen.substring(tmplen.indexOf(",") + 1, tmplen.length);
			n++;
		  }
		  this.len = new CardType.makeArray(n);
		  n = 0;
		  while (len.indexOf(",") != -1) {
			var tmpstr = len.substring(0, len.indexOf(","));
			this.len[n] = tmpstr;
			len = len.substring(len.indexOf(",") + 1, len.length);
			n++;
		  }
		  this.len[n] = len;
		
		  return this;
		},
		
		/*************************************************************************\
		   CardType setRules()
		   return the CardType object.
		\*************************************************************************/
		 setRules : function(rules) {
		  // Create the rules array.
		  if (rules.length == 0 || rules == null)
			rules = "0,1,2,3,4,5,6,7,8,9";
		  
		  var tmprules = rules;
		  n = 1;
		  while (tmprules.indexOf(",") != -1) {
			tmprules = tmprules.substring(tmprules.indexOf(",") + 1, tmprules.length);
			n++;
		  }
		  this.rules = new CardType.makeArray(n);
		  n = 0;
		  while (rules.indexOf(",") != -1) {
			var tmpstr = rules.substring(0, rules.indexOf(","));
			this.rules[n] = tmpstr;
			rules = rules.substring(rules.indexOf(",") + 1, rules.length);
			n++;
		  }
		  this.rules[n] = rules;
		
		  return this;
		}

}