//declare validator name space
passenger.validator = function(){}


/*************************************************************************\
Object CardType([String cardtype, String rules, String len, int year, 
                                        int month])
cardtype    : type of card, eg: MasterCard, Visa, etc.
rules       : rules of the cardnumber, eg: "4", "6011", "34,37".
len         : valid length of cardnumber, eg: "16,19", "13,16".
year        : year of expiry date.
month       : month of expiry date.
eg:
var VisaCard = new CardType("Visa", "4", "16");
var AmExCard = new CardType("AmEx", "34,37", "15");
\*************************************************************************/
passenger.validator.CardType = function(tmpcardtype, tmprules, tmplen) {
	
	this.objname = "object CardType";	
	this.cardNumber;  
	this.cardType = tmpcardtype;  
	this.len; 
	this.rules;
	this.expiryDate;
	this.year;
	this.month;
	
	this.getCardType = function() {
		return this.cardtype;
	}
	
	this.setCardType = function(cardtype) {
		this.cardtype = cardtype;
	}
	
	this.getExpiryDate = function() {
		return this.month + "/" + this.year;
	}
	
	this.setExpiryDate = function(year, month) {
		this.year = year;
		this.month = month;
	}
		
	this.setCardNumber = function(cardnumber) {
		this.cardnumber = cardnumber;
	}
	
	this.getCardNumber = function() {
		return this.cardnumber;
	}
		
	this.setLen = function(lenStr) {
		// Create the len array.
		if (lenStr.length == 0 || lenStr == null) {
			lenStr = "13,14,15,16,19";
		}		
		
		this.len = dojo.string.splitEscaped(lenStr, ",");
	}
	
	this.setRules = function(rulesStr) {
		// Create the rules array.
		if (rulesStr.length == 0 || rulesStr == null) {
			rulesStr = "0,1,2,3,4,5,6,7,8,9";
		}

		this.rules = dojo.string.splitEscaped(rulesStr, ",");
	}	
	
	/*************************************************************************\
	boolean checkCardNumber([String cardnumber, int year, int month])
	return true if cardnumber pass the luhncheck and the expiry date is
	valid, else return false.
	\*************************************************************************/
	this.checkCardNumber = function() {
		if (!this.isCardNumber()) {
			return false;
		}
		//if (!this.isExpiryDate()) {
			//return false;
		//}
			
		return true;
	}
	
	/*************************************************************************\
	boolean isCardNumber([String cardnumber])
	return true if cardnumber pass the luhncheck and the rules, else return
	false.
	\*************************************************************************/
	this.isCardNumber = function() {

		if (!this.luhnCheck()) {
			return false;
		}
		
		for (var n = 0; n < this.len.length; n++) {
			if (this.cardnumber.toString().length == this.len[n]) {
				for (var m = 0; m < this.rules.length; m++) {
					var headdigit = this.cardnumber.substring(0, this.rules[m].toString().length);
					if (headdigit == this.rules[m]){
						return true;
					}
				}
				return false;
			}
		}		
		return false;
	}
	

	/*************************************************************************\
	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
	\*************************************************************************/
	this.luhnCheck = function () {
		
		var CardNumber = this.cardnumber;
				
		if (! this.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;
		}
	}	
	
	/*************************************************************************\
	boolean isNum(String argvalue)
	return true if argvalue contains only numeric characters,
	else return false.
	\*************************************************************************/
	this.isNum = function(argvalue) {
		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;
	}

	this.setLen(tmplen);
	this.setRules(tmprules);
	
	return this;
}

//initialize credit card types
var Cards = new Array();
Cards[0] = new passenger.validator.CardType("MasterCard", "51,52,53,54,55", "16");
var MasterCard = Cards[0];
Cards[1] = new passenger.validator.CardType("VisaCard", "4", "13,16");
var VisaCard = Cards[1];
Cards[2] = new passenger.validator.CardType("AmExCard", "34,37", "15");
var AmExCard = Cards[2];
Cards[3] = new passenger.validator.CardType("DinersClubCard", "30,36,38", "14");
var DinersClubCard = Cards[3];
Cards[4] = new passenger.validator.CardType("DiscoverCard", "6011", "16");
var DiscoverCard = Cards[4];
Cards[5] = new passenger.validator.CardType("enRouteCard", "2014,2149", "15");
var enRouteCard = Cards[5];
Cards[6] = new passenger.validator.CardType("JCBCard", "3088,3096,3112,3158,3337,3528", "16");
var JCBCard = Cards[6];

/**
 * Validates text fields. this includes Text, text area and password
 * This method validates for following rules:
 * 1. Mandatory check
 * 2. max length check
 * 3. Data type check
 * 4. Value range check
 * 5. Email check
 */
passenger.validator.validateTextField = function(event, fieldId) {
	
	//if error page si not initialized then initialize the same
	if(passenger.error.getErrorPage() == null){
		passenger.error.initializeErrorPage();		
	}
	
	//read the element
	var validatingElement =  document.getElementById(fieldId);
	
	var isPassword = false;
	var continueValidation = true;
	
	if(validatingElement.getAttribute("type") != null && validatingElement.getAttribute("type") == "password"){
		isPassword = true;
		//stop the validation if the value is not changed. For password the value we show in the UI will be null or
		//diff from what is initally entered hence shulold stop the validation if the value is not changed
		if(validatingElement.value == validatingElement.defaultValue) {
			continueValidation = false;
		}	
	}
	
	if(continueValidation) {
		//read the attributes from the element
		var validationHintsString = validatingElement.getAttribute("validationHints");
		var elementId = validatingElement.getAttribute("elementId");
		var elementTitle = validatingElement.getAttribute("elementTitle");
		var dataType = validatingElement.getAttribute("dataType");
	
		
		//parse the validation hints	
		var validationHints = new passenger.validator.validationHints(validationHintsString);	
		
		
		//check for madatory value	
		if (validationHints.getRequired() && dojo.string.isBlank(validatingElement.value)){
			args = new Array();
			args[0] = elementTitle;	
			anErrorElement = new passenger.error.errorElement(elementId, "REQUIRED_ELEMENT", args, document.getElementById(elementId+"_Title"), REQUIRED_CHECK_FAILED, true);
			passenger.error.getErrorPage().addErrorElement(anErrorElement);
			return false;
		}
		
		//check for maximum length
		if (validationHints.getMaxLength() != null ){
			var maxLen = validationHints.getMaxLength();
			var flags = {maxlength:parseInt(maxLen)}
			if (!dojo.string.isBlank(validatingElement.value) && !dojo.validate.isText(validatingElement.value, flags)){	
				var args = new Array(elementTitle,maxLen);
				anErrorElement = new passenger.error.errorElement(elementId, "EXCEEDS_LENGTH", args, document.getElementById(elementId+"_Title"), MAXLENGTH_CHECK_FAILED, false);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;		
			}	
		}
	
		if (validationHints.getMinLength() != null ){
			var minLen = validationHints.getMinLength();
			var flags = {minlength:parseInt(minLen)}
			if (!dojo.string.isBlank(validatingElement.value) && !dojo.validate.isText(validatingElement.value, flags)){	
				var args = new Array(elementTitle,minLen);
				anErrorElement = new passenger.error.errorElement(elementId, "LESSER_LENGTH", args, document.getElementById(elementId+"_Title"), MINLENGTH_CHECK_FAILED, false);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;		
			}	
		}	
		
		//check for data type
		if (dataType != null) {
			//check for number
			if (dataType == 5001) {
				if(validatingElement.value.length > 0 && (!dojo.validate.isInteger(validatingElement.value) || validatingElement.value.length > 9)) {
					var args = new Array(elementTitle);
					anErrorElement = new passenger.error.errorElement(elementId, "NOT_VALID_NUMBER", args, document.getElementById(elementId+"_Title"), DATATYPE_CHECK_FAILED, false);
					passenger.error.getErrorPage().addErrorElement(anErrorElement);
					return false;						
				}
			}
			//check for double
			if (dataType == 5007) {
				if(validatingElement.value.length > 0 && !dojo.validate.isInteger(validatingElement.value)) {
					var args = new Array(elementTitle);
					anErrorElement = new passenger.error.errorElement(elementId, "NOT_VALID_NUMBER", args, document.getElementById(elementId+"_Title"), DATATYPE_CHECK_FAILED, false);
					passenger.error.getErrorPage().addErrorElement(anErrorElement);
					return false;						
				}
			}
			
		}
		
		//check for value range
		if(validationHints.getMinimumValue() != null && validationHints.getMaximumValue() != null && validatingElement.value != "") {
			var flags = {min:parseInt(validationHints.getMinimumValue()),max:parseInt(validationHints.getMaximumValue())}
			if(!dojo.validate.isInRange(validatingElement.value, flags)) {			
				var args = new Array(elementTitle, validationHints.getMinimumValue(), validationHints.getMaximumValue());
				anErrorElement = new passenger.error.errorElement(elementId, "VALUE_NOT_IN_RANGE", args, document.getElementById(elementId+"_Title"), RANGE_CHECK_FAILED, false);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;									
			}
		}
		
		//check for minimum value
		if(validationHints.getMinimumValue() != null && validatingElement.value != ""){
			var min = parseInt(validationHints.getMinimumValue());
			if (min > validatingElement.value){	
				var args = new Array(elementTitle,validationHints.getMinimumValue());
				anErrorElement = new passenger.error.errorElement(elementId, "ELEMENTS_MUST_BE_GREATER", args, document.getElementById(elementId+"_Title"), MIN_VALUE_CHECK_FAILED, false);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;		
			}
		}

		//check for maximum value
		if(validationHints.getMaximumValue() != null && validatingElement.value != ""){
			var max = parseInt(validationHints.getMaximumValue());
			if (max < validatingElement.value){	
				var args = new Array(elementTitle, validationHints.getMaximumValue());
				anErrorElement = new passenger.error.errorElement(elementId, "ELEMENTS_MUST_NOT_EXCEED", args, document.getElementById(elementId+"_Title"), MAX_VALUE_CHECK_FAILED, false);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;		
			}
		}
		
		//check for email	
		if(validationHints.getIsEmail() && validatingElement.value != "") {
			var flags = {min:parseInt(validationHints.getMinimumValue()),max:parseInt(validationHints.getMaximumValue())}
			if(!dojo.validate.isEmailAddress(validatingElement.value, flags)) {			
				var args = new Array(elementTitle);
				anErrorElement = new passenger.error.errorElement(elementId, "INVALID_EMAIL", args, document.getElementById(elementId+"_Title"), EMAIL_CHECK_FAILED, false);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;									
			}
		}
		
		//check for credit card
		if(validationHints.getIsValidCC()) {
			var cardType = "";
			switch(parseInt(validationHints.getCcType())) {
				case 1: cardType = AmExCard; break;//American Express
				case 2: cardType = MasterCard; break;//Mastercard
				case 3: cardType = VisaCard; break;//Visa
				case 4: cardType = DiscoverCard; break;//Discover
				case 5: cardType = DinersClubCard; break;//Diners Club
				case 6: cardType = DinersClubCard; break;//Carte Blanch
				case 7: cardType = MasterCard; break;//Eurocard
				case 8: cardType = JCBCard; break;//JCB
				case 9: cardType = enRouteCard; break;//Enroute
			}
						
			//if element is already validated and marked as pass then do not valid again unless the new value is provided. 
			if( !(validatingElement.value == "Verified" && validatingElement.defaultValue == "pass")){
				cardType.setCardNumber(validatingElement.value);
				if(cardType == "" || !cardType.checkCardNumber()) {
					var args = new Array(elementTitle);
					anErrorElement = new passenger.error.errorElement(elementId, "NOT_VALID_CC", args, document.getElementById(elementId+"_Title"), CC_CHECK_FAILED, false);
					passenger.error.getErrorPage().addErrorElement(anErrorElement);
					validatingElement.defaultValue = "";					
					return false;									
				}else{
					validatingElement.value = "Verified";
					validatingElement.defaultValue = "pass";
				}
			}
		}
		
		//check for not in specific list -- this is also used for requried check of list box
		if(validationHints.getNotInList().length > 0){
			for(var i=0; i < validationHints.getNotInList().length; i++) {
				if(validationHints.getNotInList()[i] == validatingElement.value){
					args = new Array(elementTitle, validatingElement.value, validationHints.getNotInList());
					anErrorElement = new passenger.error.errorElement(elementId, "VALUE_CANT_BE_IN_LIST", args, document.getElementById(elementId+"_Title"), OTHER_ERROR, true);
					passenger.error.getErrorPage().addErrorElement(anErrorElement);
					return false;				
				}
			}
		}
		
		//check for profanity
		if(validationHints.getCheckProfanity()){
			if(isProfanity(validatingElement.value)){
				args = new Array();
				args[0] = elementTitle;	
				anErrorElement = new passenger.error.errorElement(elementId, "CHECK_PROFANITY_FAILED", args, document.getElementById(elementId+"_Title"), CHECK_PROFANITY_FAILED, true);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;
			}
		}
		
		//check for alpha numeric
		if(validationHints.getAlphaNumeric()){
			if(!passenger.validator.isAlphaNumeric(validatingElement.value)){
				args = new Array();
				args[0] = elementTitle;	
				anErrorElement = new passenger.error.errorElement(elementId, "SHOULD_BE_ALPHA_NUMERIC", args, document.getElementById(elementId+"_Title"), OTHER_ERROR, true);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;
			}
		}
		
		//check for spaces is allowed or not
		if(!validationHints.getAllowSpace()){
			if(validatingElement.value.indexOf(" ") > -1){
				args = new Array();
				args[0] = elementTitle;	
				anErrorElement = new passenger.error.errorElement(elementId, "SHOULD_NOT_HAVE_SPACES", args, document.getElementById(elementId+"_Title"), OTHER_ERROR, true);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;
			}
		}		
	}	
} 

/**
 * Checks if the element content is alpha numeric or not
 * Alpha numeric means it should be with in 
 * 123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
 */
passenger.validator.isAlphaNumeric = function(elementValue) {

	var x1 = /^[a-z\d]/i // Check for start with alphanumerics (this may not be requried)
	var x2 = /[a-z]/i // a letter present
	var x3 = /\d/ // a digit present
	var x4 = /[^a-z\d]/i // Check for non alpha numeric characters
	var alphaNumeric = x1.test(elementValue) && x2.test(elementValue) && x3.test(elementValue) && !x4.test(elementValue)
	
	return alphaNumeric;
}

/**
 * Validates radio button fields. 
 * This method validates for following rules:
 * 1. Mandatory check
 */
passenger.validator.validateRadioField = function(event, fieldId) {
	var radioElements = document.getElementsByName(fieldId);	
	var aRadioElement = radioElements[0];
	var elementId =  aRadioElement.getAttribute("elementId");

	//read the attributes from the element
	var validationHintsString = aRadioElement.getAttribute("validationHints");
	var elementId = aRadioElement.getAttribute("elementId");
	var elementTitle = aRadioElement.getAttribute("elementTitle");
	
	//parse the validation hints	
	var validationHints = new passenger.validator.validationHints(validationHintsString);	
	if( validationHints.getRequired()) {
		var isSelected = false;
		for(var i=0; i < radioElements.length; i++) {
			if(radioElements[i].checked) {
				isSelected = true;
				break;
			}			
		}			
		if(!isSelected){
			args = new Array(elementTitle);
			anErrorElement = new passenger.error.errorElement(elementId, "REQUIRED_ELEMENT", args, document.getElementById(elementId+"_Title"), REQUIRED_CHECK_FAILED, true);
			passenger.error.getErrorPage().addErrorElement(anErrorElement);
			return false;			
		}
	}
}

/**
 * Validates List fields. 
 * This method validates for following rules:
 * 1. Mandatory check
 * 2. Not in specific list (used in case we don't want user to select first item in the list
 */
passenger.validator.validateListField = function(event, fieldId) {
	
	//read the element
	var validatingElement =  document.getElementById(fieldId);
	
	//read the attributes from the element
	var validationHintsString = validatingElement.getAttribute("validationHints");
	var elementId = validatingElement.getAttribute("elementId");
	var elementTitle = validatingElement.getAttribute("elementTitle");
	
	//parse the validation hints	
	var validationHints = new passenger.validator.validationHints(validationHintsString);	
	
	//check for mandatory
	if(validationHints.getRequired() && validatingElement.selectedIndex < 0) {
		args = new Array(elementTitle);
		anErrorElement = new passenger.error.errorElement(elementId, "REQUIRED_ELEMENT", args, document.getElementById(elementId+"_Title"), REQUIRED_CHECK_FAILED, true);
		passenger.error.getErrorPage().addErrorElement(anErrorElement);
		return false;
	}
	
	//check for not in specific list -- this is also used for requried check of list box
	if(validationHints.getNotInList().length > 0){
		var selectedElement = validatingElement.options[validatingElement.selectedIndex]
		for(var i=0; i < validationHints.getNotInList().length; i++) {
			if(validationHints.getNotInList()[i] == selectedElement.value){
				args = new Array(elementTitle);
				anErrorElement = new passenger.error.errorElement(elementId, "REQUIRED_ELEMENT", args, document.getElementById(elementId+"_Title"), REQUIRED_CHECK_FAILED, true);
				passenger.error.getErrorPage().addErrorElement(anErrorElement);
				return false;				
			}
		}
	}
		
}

/**
 * Validates List fields. 
 * This method validates for following rules:
 * 1. Mandatory check
 * 2. Minimum selection check
 */
passenger.validator.validateCheckboxField = function(event, fieldId) {
	var checkBoxFields = new Array();
	//variable to store how many check box elements are selected
	var selectionCount = 0;
	
	/**
	 * The ids for the check box elements are created by tapestry and we don't have control on this.
	 * however the id generation uses the id that we have given along with some suffixes. Example: if the
	 * id for the element is 10 and the number of elements is 5 then following ids are generated for the
	 * elements in this group: 10, 10_0, 10_1, 10_2, 10_3
	 */
	 checkBoxFields[checkBoxFields.length]= document.getElementById(fieldId);	 
	 if(document.getElementById(fieldId) != null && document.getElementById(fieldId).checked){
	 	selectionCount = selectionCount + 1;
	 }
	 var aCheckBox = null;
	 for(var i=0; i < 1000; i++) {
		aCheckBox = document.getElementById(fieldId+"_"+i);
		if(aCheckBox != null){
			checkBoxFields[checkBoxFields.length] = aCheckBox;
			 if(aCheckBox.checked){
			 	selectionCount = selectionCount + 1;
			 }
		}else{
			break;
		}
	 }	 
	 
	//read the element
	var validatingElement =  document.getElementById(fieldId);
	
	//if no element with the given id then complete the validation with out failures. 
	if (validatingElement == null) {
		return true;
	}
	
	//read the attributes from the element
	var validationHintsString = validatingElement.getAttribute("validationHints");
	var elementId = validatingElement.getAttribute("elementId");
	var elementTitle = validatingElement.getAttribute("elementTitle");
	
	//parse the validation hints	
	var validationHints = new passenger.validator.validationHints(validationHintsString);	
	
	//check for required
	if(validationHints.getRequired()){
		if(selectionCount == 0){
			args = new Array(elementTitle);
			anErrorElement = new passenger.error.errorElement(elementId, "REQUIRED_ELEMENT", args, document.getElementById(elementId+"_Title"), REQUIRED_CHECK_FAILED, true);
			passenger.error.getErrorPage().addErrorElement(anErrorElement);
			return false;
		}
	}	 
	
	//check for minimum selections
	if(validationHints.getMinSelections() != null){
		if(selectionCount < parseInt(validationHints.getMinSelections())){
			args = new Array(validationHints.getMinSelections(), elementTitle);
			anErrorElement = new passenger.error.errorElement(elementId, "MINIMUM_SELECTION_FAILED", args, document.getElementById(elementId+"_Title"), OTHER_ERROR, true);
			passenger.error.getErrorPage().addErrorElement(anErrorElement);
			return false;
		}				
	}

	//check for maximum selections
	if(validationHints.getMaxSelections() != null){
		if(selectionCount > parseInt(validationHints.getMaxSelections())){
			args = new Array(validationHints.getMaxSelections(), elementTitle);
			anErrorElement = new passenger.error.errorElement(elementId, "MAXIMUM_SELECTION_FAILED", args, document.getElementById(elementId+"_Title"), OTHER_ERROR, true);
			passenger.error.getErrorPage().addErrorElement(anErrorElement);
			return false;
		}				
	}	
}

/**
 * Validates Date fields. 
 * This method validates for following rules:
 * 1. Mandatory check
 * 2. Can't be greater than today
 * 3. Can't be less than today
 */
passenger.validator.validateDateField = function(event, fieldId) {
	var validatingElement_month =  document.getElementById(fieldId);
	var validatingElement_year =  document.getElementById(fieldId + "_year");
	var validatingElement_day =  document.getElementById(fieldId + "day");
	var validationHintsString = validatingElement_month.getAttribute("validationHints");
	var elementId = validatingElement_month.getAttribute("elementId");
	var elementTitle = validatingElement_month.getAttribute("elementTitle");
	
	var validationHints = new passenger.validator.validationHints(validationHintsString);
	if(validationHints.getRequired()) {
		if((validatingElement_month && validatingElement_month.value == -1) 
				|| (validatingElement_year && validatingElement_year.value == -1)
				|| (validatingElement_day && validatingElement_day.value == -1)) {
			var args = new Array(elementTitle);
			anErrorElement = new passenger.error.errorElement(elementId, "REQUIRED_ELEMENT", args, document.getElementById(elementId+"_Title"), REQUIRED_CHECK_FAILED, true);
			passenger.error.getErrorPage().addErrorElement(anErrorElement);
			return false;
		}
	} 

	return true;
}

/**
 * Validates File Field. 
 * This method validates for following rules:
 * 1. Mandatory check
 */
passenger.validator.validateFile = function(event, fieldId) {
	//read the element
	var validatingElement =  document.getElementById(fieldId);
	
	//read the attributes from the element
	var validationHintsString = validatingElement.getAttribute("validationHints");
	var elementId = validatingElement.getAttribute("elementId");
	var elementTitle = validatingElement.getAttribute("elementTitle");	
	

	//parse the validation hints	
	var validationHints = new passenger.validator.validationHints(validationHintsString);	
	
	//check for mandatory
	if(validationHints.getRequired() && (parseInt(document.getElementById(elementId+"_fileId").value) < 1000)) {
		args = new Array(elementTitle);
		anErrorElement = new passenger.error.errorElement(elementId, "REQUIRED_ELEMENT", args, null, REQUIRED_CHECK_FAILED, false);
		passenger.error.getErrorPage().addErrorElement(anErrorElement);
		
		//also display error below the file upload
		var  uploadErrorPage = new passenger.error.errorPage();
		var anError = new passenger.error.errorElement(elementId, "INVALID_FILE_NAME", [], null, OTHER_ERROR, false);		
		uploadErrorPage.addErrorElement(anError);
		uploadErrorPage.generateErrorPage(elementId+"_attach_error_div");		
		return false;
	}	
	
}

/**
 * Create validations hints objects from the string. Validation hints
 * string is expected in the following format
 * REQUIRED=true/false,MAX_LENGTH=10,DATA_TYPE=1,MIN_VALUE=100,MAX_VALUE=10000,ISEMAIL=true,MIN_SELECTIONS=3,NOT_IN=-1:1,CHECK_PROFANITY=true/false,ALPHA_NUMERIC=true
 */
passenger.validator.validationHints = function(validationHintsAsString) {
	var hints = [];
	if(validationHintsAsString != null) {	
		hints = dojo.string.splitEscaped(validationHintsAsString, ",");
	}
	var required = false;
	var maxLength = null;
	var minLength = null;	
	var dataType = 1; //1 string, 2 - integer, 3 - float, 4 - date
	var ccType = 1; //1 am, 2 mc, 3 vi, 4 di, 5 dc, 6 bl, 7 ec, 8 jcb, 9 er
	var minimumValue = null;
	var maximumValue = null;
	var isEmail = false;
	var isValidCC = false;
	var alphaNumeric = false;	
	var minSelections = null;
	var maxSelections = null;	
	var notInList = new Array();
	var checkProfanity = false;
	var hintValue = null;
	var allowSpace = true;
	
	for(var i=0; i < hints.length; i++){
		hintValue = hints[i];
		hintValue = hintValue.replace(/\+/g, " ");
		hintValue = Url.decode(hintValue);
		if (dojo.string.startsWith(hintValue,"REQUIRED",true)){
			required = dojo.string.splitEscaped(hintValue, "=")[1];
			if(dojo.string.splitEscaped(hintValue, "=")[1] == 'false'){
				required = false;
			}else{ 			
				required = true;
			}
		}else if (dojo.string.startsWith(hintValue,"MAX_LENGTH",true)){
			maxLength = dojo.string.splitEscaped(hintValue, "=")[1];
		}else if (dojo.string.startsWith(hintValue,"MIN_LENGTH",true)){
			minLength = dojo.string.splitEscaped(hintValue, "=")[1];			
		}else if (dojo.string.startsWith(hintValue,"DATA_TYPE",true)){
			dataType = dojo.string.splitEscaped(hintValue, "=")[1];
		}else if (dojo.string.startsWith(hintValue,"CARD_TYPE",true)){
			ccType = dojo.string.splitEscaped(hintValue, "=")[1];
		}else if (dojo.string.startsWith(hintValue,"MIN_VALUE",true)){
			minimumValue = dojo.string.splitEscaped(hintValue, "=")[1];
		}else if (dojo.string.startsWith(hintValue,"MAX_VALUE",true)){
			maximumValue = dojo.string.splitEscaped(hintValue, "=")[1];
		}else if (dojo.string.startsWith(hintValue,"ISEMAIL",true)){
			if(dojo.string.splitEscaped(hintValue, "=")[1] == 'false') {
				isEmail = false;
			}else{
				isEmail = true;
			}
		}else if (dojo.string.startsWith(hintValue,"CHECK_CREDIT_CARD",true)){
			if(dojo.string.splitEscaped(hintValue, "=")[1] == 'false') {
				isValidCC = false;
			}else{
				isValidCC = true;
			}
		}else if (dojo.string.startsWith(hintValue,"MIN_SELECTIONS",true)){
			minSelections = dojo.string.splitEscaped(hintValue, "=")[1];
		}else if (dojo.string.startsWith(hintValue,"MAX_SELECTIONS",true)){
			maxSelections = dojo.string.splitEscaped(hintValue, "=")[1];
		}else if (dojo.string.startsWith(hintValue,"NOT_IN",true)){
			notInList = dojo.string.splitEscaped(dojo.string.splitEscaped(hintValue, "=")[1],":");
		}else if (dojo.string.startsWith(hintValue,"CHECK_PROFANITY",true)){
			if(dojo.string.splitEscaped(hintValue, "=")[1] == 'false') {
				checkProfanity = false;
			}else{
				checkProfanity = true;
			}
			
		}else if (dojo.string.startsWith(hintValue,"ALPHA_NUMERIC",true)){
			if(dojo.string.splitEscaped(hintValue, "=")[1] == 'false') {
				alphaNumeric = false;
			}else{
				alphaNumeric = true;
			}
			
		}else if (dojo.string.startsWith(hintValue,"ALLOW_SPACE",true)){
			if(dojo.string.splitEscaped(hintValue, "=")[1] == 'false') {
				allowSpace = false;
			}else{
				allowSpace = true;
			}
		}
	}
	
	this.getRequired = function() {
		return required;
	}	
	this.getMaxLength = function() {
		return maxLength;
	}
	this.getMinLength = function() {
		return minLength;
	}
	this.getDataType = function() {
		return dataType;
	}
	this.getCcType = function() {
		return ccType;
	}
	this.getMinimumValue = function() {
		return minimumValue;
	} 
	this.getMaximumValue = function() {
		return maximumValue;
	}
	this.getIsEmail = function() {
		return isEmail;
	}
	this.getIsValidCC = function() {
		return isValidCC;
	}
	this.getMinSelections = function() {
		return minSelections;
	}	
	this.getMaxSelections = function() {
		return maxSelections;
	}
	this.getCheckProfanity = function() {
		return checkProfanity;
	}
	this.getNotInList = function() {
		return notInList;
	}	
	this.getAlphaNumeric = function() {
		return alphaNumeric;
	}	
	this.getAllowSpace = function() {
		return allowSpace;
	}		
}	

/**
*
*  URL encode / decode
*  http://www.webtoolkit.info/
*
**/

var Url = {
	// public method for url encoding
	encode : function (string) {
		return escape(this._utf8_encode(string));
	},
	// public method for url decoding
	decode : function (string) {
		return this._utf8_decode(unescape(string));
	},
	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
		for (var n = 0; n < string.length; n++) {
			var c = string.charCodeAt(n);
			if (c < 128) {
				utftext += String.fromCharCode(c);
			} else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			} else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
		}
		return utftext;
	},
	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
		while ( i < utftext.length ) {
			c = utftext.charCodeAt(i);
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			} else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			} else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
		}
		return string;
	}
}