var validateMe = false;	

function Validator(frmname) {
	this.formobj = document.getElementById(frmname);
	if(!this.formobj) {
		alert("BUG: Could not get Form object "+frmname);
		return;
	}
	if(this.formobj.onsubmit) {
		this.formobj.old_onsubmit = this.formobj.onsubmit;
		this.formobj.onsubmit = null;
	} else {
		this.formobj.old_onsubmit = null;
	}
	this.formobj.onsubmit = form_submit_handler;
	this.addValidation = add_validation;
	this.setAddnlValidationFunction = set_addnl_vfunction;
	this.clearOneValidation = clear_one_validation;
	this.clearAllValidations = clear_all_validations;
	this.submitbutton = function(bname) {
		if (document.getElementById(bname)) { AddListener(bname,"click",function() { validateMe = true; },true); }
	}
	this.backbutton = function(buton) {
		if (document.getElementById(buton)) { AddListener(buton,"click",function() { validateMe = false; },true); }
	}
}
function set_addnl_vfunction(functionname) {
	this.formobj.addnlvalidation = functionname;
}
function clear_all_validations() {
	for(itr=0;itr<this.formobj.elements.length;itr++)	{
		this.formobj.elements[itr].validationset = null;
	}
}
function clear_one_validation(obj) {
	for(itr=0;itr<this.formobj.elements.length;itr++) {
		//console.log(this.formobj.elements[itr].validationset);
		if ((this.formobj.elements[itr].validationset)&&(this.formobj.elements[itr].validationset.itemobj.id == obj)) {
			this.formobj.elements[itr].validationset = null;
		//console.log(this.formobj.elements[itr].validationset.itemobj.id);
		}
	}
}
function form_submit_handler() {
	if (validateMe) {
		flags = 0;
		for(itr=0;itr<this.elements.length;itr++) {
			if (!this.elements[itr].disabled) {
				if(this.elements[itr].validationset && !this.elements[itr].validationset.validate()) {
					flags++;
				}
			}
		}
		if(this.addnlvalidation) {
			str =" var ret = "+this.addnlvalidation+"()";
			eval(str);
			if(!ret) return ret;
		}
		var fail = document.getElementById("fail");
		if (fail) {	document.getElementById("fail").style.display = (flags > 0) ? "block" : "none";	}
		if (flags > 0) { return false; }
	} else {
		return true;
	}
}
function flagField(field,flag,msg) {
	var warnField = document.getElementById(field);
	warnField.className = flag ? warnField.objclass : warnField.objclass + "warn";
	if (warnField.label) {
		warnField.label.className = flag ? warnField.labelClass : warnField.labelClass + "warn";
		var labelBox = document.getElementById(warnField.id + "info");
		if (labelBox) {
			labelBox.style.display = (flag) ? "none" : "block";
			labelBox.obj.innerHTML = msg;
		} else {
			if (!flag) {
				var mark = document.createTextNode('?');
				var info = document.createElement('div');
				var itxt = document.createTextNode(msg);
				info.id = warnField.id + "info";
				info.className = "info";
				info.appendChild(mark);
				warnField.label.appendChild(info);
				info.obj = document.createElement('div');
				info.obj.id = warnField.id + "infobox";
				info.obj.className = "infobox";
				info.obj.appendChild(itxt);
				info.obj.style.top = '-600px';
				info.bOverlay = false;
				info.setTimeShow;
				info.setTimeHide;
				info.objPos = FindPos(info);
				document.getElementsByTagName('body')[0].appendChild(info.obj);
				info.show = function() {
					var id = this.id;
					this.obj.style.left = this.objPos.x + 18 + 'px';
					this.obj.style.top = this.objPos.y + 16 + 'px';
					this.bOverlay = true;
				}
				info.hide = function() {
					obj = document.getElementById(this.id+"box");
					this.bOverlay = false;
					obj.style.top = "-600px";
				}
				info.startShow = function() {
					if(this.bOverlay) {
						clearTimeout(this.setTimeHide);
					} else {
						var id = this.id;
						this.setTimeShow = setTimeout("document.getElementById('"+id+"').show(this)",500);
					}
				}
				info.startHide = function() {
					if(this.bOverlay) {
						var id = this.id;
						this.setTimeHide = setTimeout("document.getElementById('"+id+"').hide(this)",400);
					} else {
						clearTimeout(this.setTimeShow);
					}
				}
				info.onclick = info.show;
				info.onmouseover = info.startShow;
				info.onmouseout = info.startHide;
			}
		}
	}
}
function add_validation(itemname,descriptor,errstr) {
	if(!this.formobj) {
		alert("BUG: the form object is not set properly");
		return;
	}
	var itemobj = this.formobj[itemname];
	if(!itemobj) {
		alert("BUG: Couldnot get the input object named: "+itemname);
		return;
	}
	if(!itemobj.validationset) {
	  itemobj.validationset = new ValidationSet(itemobj);
	}
	itemobj.objclass = itemobj.className;
	var formLabels = document.getElementsByTagName("label");
	for (i=0;i<formLabels.length;i++) {
		if (formLabels[i].htmlFor == itemobj.id) {
			itemobj.label = formLabels[i];
			itemobj.labelClass = formLabels[i].className;
			itemobj.labelText = formLabels[i].innerHTML;
		}
	}
	itemobj.validationset.add(descriptor,errstr);
}
function ValidationDesc(inputitem,desc,error) {
	this.desc = desc;
	this.error = error;
	this.itemobj = inputitem;
	this.validate = vdesc_validate;
}
function vdesc_validate() {
	if(!V2validateData(this.desc,this.itemobj,this.error)) {
		//this.itemobj.focus();
		return false;
	}
	return true;
}
function ValidationSet(inputitem) {
	this.vSet = new Array();
	this.add = add_validationdesc;
	this.validate = vset_validate;
	this.itemobj = inputitem;
}
function add_validationdesc(desc,error) {
	this.vSet[this.vSet.length] = new ValidationDesc(this.itemobj,desc,error);
}
function vset_validate() {
	for(var itr=0;itr<this.vSet.length;itr++) {
		if(!this.vSet[itr].validate()) {
			return false;
		}
	}
	return true;
}
function validateEmailv2(email) {
	/*
	var emailExp = /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/;
	if(email.match(emailExp)){
		return true;
	} else {
		return false;
	}
	*/
	email = email.replace(/^\s*/, "").replace(/\s*$/, "");
	if(email.length <= 0) {
		return true;
	}
	var splitted = email.match("^(.+)@(.+)$");
	if(splitted == null) return false;
	if(splitted[1] != null) {
		var regexp_user = /^\"?[\w-_\.\+\-]*\"?$/;
		if(splitted[1].match(regexp_user) == null) return false;
	}
	if(splitted[2] != null) {
		var regexp_domain = /^[\w-\.]+\.[A-Za-z0-9\-]{2,4}$/;
		if(splitted[2].match(regexp_domain) == null) {
			var regexp_ip =/^\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]$/;
			if(splitted[2].match(regexp_ip) == null) return false;
		}
		return true;
	}
	return false;
	
	//alternate email checker...
	/*
	var emailFilter=/^.+@.+\..{2,4}$/;
    if (!(emailFilter.test(strng))) { 
		return false;
    }
    else {
	//test email for illegal characters
		var illegalChars= /[\(\)\<\>\,\;\:\\\"\[\]]/
		if (strng.match(illegalChars)) {
			return false;
		}
	}
	return true;
	*/
}

function V2validateData(strValidateStr,objValue,strError) { 
	var epos = strValidateStr.search("="); 
	var  command  = ""; 
	var  cmdvalue = ""; 
	if(epos >= 0) { 
		command  = strValidateStr.substring(0,epos); 
		cmdvalue = strValidateStr.substr(epos+1); 
	} else { 
		command = strValidateStr; 
	} 
    switch(command) { 
		case "req": 
		case "required": { 
			if(objValue.value.length == 0) { 
				if(!strError || strError.length == 0) { 
					strError = objValue.name + " : Required Field"; 
				}
				flagField(objValue.id,false,strError);
				return false;
			} else {
				flagField(objValue.id,true,strError);
			}
			break;             
		}//case required 
        case "maxlength": 
        case "maxlen": 
          { 
             if(eval(objValue.value.length) >  eval(cmdvalue)) { 
               if(!strError || strError.length == 0) { 
                 strError = objValue.name + " : "+cmdvalue+" characters maximum "; 
               } 
               alert(strError + "\n[Current length = " + objValue.value.length + " ]"); 
               return false; 
             } 
             break; 
          }//case maxlen 
        case "minlength": 
        case "minlen": 
           { 
             if(eval(objValue.value.length) <  eval(cmdvalue)) 
             { 
               if(!strError || strError.length ==0) 
               { 
                 strError = objValue.name + " : " + cmdvalue + " characters minimum  "; 
               }               
               alert(strError + "\n[Current length = " + objValue.value.length + " ]"); 
               return false;                 
             } 
             break; 
            }//case minlen 
        case "alnum": 
        case "alphanumeric": 
           { 
              var charpos = objValue.value.search("[^A-Za-z0-9]"); 
              if(objValue.value.length > 0 &&  charpos >= 0) 
              { 
               if(!strError || strError.length ==0) 
                { 
                  strError = objValue.name+": Only alpha-numeric characters allowed "; 
                } 
                alert(strError + "\n [Error character position " + eval(charpos+1)+"]"); 
                return false; 
              } 
              break; 
           }//case alphanumeric 
        case "num": 
        case "numeric": 
           { 
              var charpos = objValue.value.search("[^0-9]"); 
              if(objValue.value.length > 0 &&  charpos >= 0) 
              { 
                if(!strError || strError.length ==0) 
                { 
                  strError = objValue.name+": Only digits allowed "; 
                }               
                alert(strError + "\n [Error character position " + eval(charpos+1)+"]"); 
                return false; 
              } 
              break;               
           }//numeric 
        case "alphabetic": 
        case "alpha": 
           { 
              var charpos = objValue.value.search("[^A-Za-z]"); 
              if(objValue.value.length > 0 &&  charpos >= 0) 
              { 
                  if(!strError || strError.length ==0) 
                { 
                  strError = objValue.name+": Only alphabetic characters allowed "; 
                }                             
                alert(strError + "\n [Error character position " + eval(charpos+1)+"]"); 
                return false; 
              } 
              break; 
           }//alpha 
		case "alnumhyphen":
			{
              var charpos = objValue.value.search("[^A-Za-z0-9\-_]"); 
              if(objValue.value.length > 0 &&  charpos >= 0) 
              { 
                  if(!strError || strError.length ==0) 
                { 
                  strError = objValue.name+": characters allowed are A-Z,a-z,0-9,- and _"; 
                }                             
                alert(strError + "\n [Error character position " + eval(charpos+1)+"]"); 
                return false; 
              } 			
			break;
			}
        case "lt": 
        case "lessthan": { 
            if(isNaN(objValue.value)) { 
              alert(objValue.name+": Should be a number "); 
              return false; 
            } 
            if(eval(objValue.value) >=  eval(cmdvalue)) { 
              if(!strError || strError.length ==0) { 
                strError = objValue.name + " : value should be less than "+ cmdvalue; 
              }               
              alert(strError); 
              return false;                 
             }             
            break; 
         }//case lessthan 
        case "gt": 
        case "greaterthan": 
         { 
            if(isNaN(objValue.value)) { 
              alert(objValue.name+": Should be a number "); 
              return false; 
            } 
             if(eval(objValue.value) <=  eval(cmdvalue)) { 
               if(!strError || strError.length == 0) { 
                 strError = objValue.name + " : value should be greater than "+ cmdvalue; 
               }               
               alert(strError); 
               return false;                 
             }             
            break; 
         }//case greaterthan 
        case "regexp": 
         { 
		 	if(objValue.value.length > 0)
			{
	            if(!objValue.value.match(cmdvalue)) 
	            { 
	              if(!strError || strError.length ==0) 
	              { 
	                strError = objValue.name+": Invalid characters found "; 
	              }                                                               
	              alert(strError); 
	              return false;                   
	            } 
			}
           break; 
         }//case regexp 
		case "equalto": {
			if(objValue.value == cmdvalue) {
				if(!strError || strError.length == 0) { 
					strError = objValue.name+": Please select a valid option.";
				}
				flagField(objValue.id,false,strError);
				return false; 
			} else {
				flagField(objValue.id,true,strError);
			}
			//break;
		}
		case "email": { 
			if(!validateEmailv2(objValue.value)) { 
				if(!strError || strError.length == 0) { 
					strError = objValue.name+": Enter a valid Email address "; 
				}                                               
				flagField(objValue.id,false,strError);
				return false; 
			} else {
				flagField(objValue.id,true,strError);
			}
           break; 
		}//case email 
		case "dontselect": { 
			/*
			if(objValue.selectedIndex == null) { 
				alert("BUG: dontselect command for non-select Item"); 
				return false; 
			}
			*/
			if(objValue.selectedIndex == eval(cmdvalue)) { 
				if(!strError || strError.length ==0) { 
					strError = objValue.name+": Please Select one option "; 
				}                                                               
				flagField(objValue.id,false,strError);
				return false;
			} else {
				flagField(objValue.id,true,strError);
			}
			break; 
		}//case dontselect
		case "creditcard": {
			var acctType = document.getElementById("ddlAccountType");
			if (acctType) {
		  		if (acctType.selectedIndex != (acctType.options.length-1)) {
					if(!checkCreditCard()) {
						if(!strError || strError.length == 0) { 
	            			strError = "Please enter a valid credit card number.";
						}
						flagField(objValue.id,false,strError);
						return false; 
					} else {
						flagField(objValue.id,true,strError);
					}
		  		}
			}
		}
		break;
    }//switch 
    return true; 
}

var ccErrorNo = 0;
var ccErrors = new Array ()

ccErrors [0] = "Unknown card type";
ccErrors [1] = "No card number provided";
ccErrors [2] = "Credit card number is in invalid format";
ccErrors [3] = "Credit card number is invalid";
ccErrors [4] = "Credit card number has an inappropriate number of digits";

function checkCreditCard () {
	var cardnumber = document.getElementById("txtAccount").value;
	var cardType = document.getElementById("ddlAccountType").selectedIndex;
	
	var cards = new Array();
	cards [0] = {name: "Invalid"};
	cards [1] = {name: "American Express",length: "15",prefixes: "34,37",checkdigit: true};
	cards [2] = {name: "Discover",length: "16",prefixes: "6011,622,64,65",checkdigit: true};
	cards [3] = {name: "MasterCard",length: "16",prefixes: "51,52,53,54,55",checkdigit: true};
	cards [4] = {name: "Visa",length: "13,16",prefixes: "4",checkdigit: true};
	           
  // Establish card type
  /*
  var cardType = -1;
  for (var i=0; i<cards.length; i++) {

    // See if it is this card (ignoring the case of the string)
    if (cardname.toLowerCase () == cards[i].name.toLowerCase()) {
      cardType = i;
      break;
    }
  }
  */
  // If card type not found, report an error
  if (cardType == 0) {
     ccErrorNo = 0;
     return false; 
  }
   
  // Ensure that the user has provided a credit card number
  if (cardnumber.length == 0)  {
     ccErrorNo = 1;
     return false; 
  }
    
  // Now remove any spaces from the credit card number
  cardnumber = cardnumber.replace (/\s/g, "");
  
  // Check that the number is numeric
  var cardNo = cardnumber
  var cardexp = /^[0-9]{13,19}$/;
  if (!cardexp.exec(cardNo))  {
     ccErrorNo = 2;
     return false; 
  }
       
  // Now check the modulus 10 check digit - if required
  if (cards[cardType].checkdigit) {
    var checksum = 0;                                  // running checksum total
    var mychar = "";                                   // next char to process
    var j = 1;                                         // takes value of 1 or 2
  
    // Process each digit one by one starting at the right
    var calc;
    for (i = cardNo.length - 1; i >= 0; i--) {
    
      // Extract the next digit and multiply by 1 or 2 on alternative digits.
      calc = Number(cardNo.charAt(i)) * j;
    
      // If the result is in two digits add 1 to the checksum total
      if (calc > 9) {
        checksum = checksum + 1;
        calc = calc - 10;
      }
    
      // Add the units element to the checksum total
      checksum = checksum + calc;
    
      // Switch the value of j
      if (j ==1) {j = 2} else {j = 1};
    } 
  
    // All done - if checksum is divisible by 10, it is a valid modulus 10.
    // If not, report an error.
    if (checksum % 10 != 0)  {
     ccErrorNo = 3;
     return false; 
    }
  }  

  // The following are the card-specific checks we undertake.
  var LengthValid = false;
  var PrefixValid = false; 
  var undefined; 

  // We use these for holding the valid lengths and prefixes of a card type
  var prefix = new Array ();
  var lengths = new Array ();
    
  // Load an array with the valid prefixes for this card
  prefix = cards[cardType].prefixes.split(",");
      
  // Now see if any of them match what we have in the card number
  for (i=0; i<prefix.length; i++) {
    var exp = new RegExp ("^" + prefix[i]);
    if (exp.test (cardNo)) PrefixValid = true;
  }
      
  // If it isn't a valid prefix there's no point at looking at the length
  if (!PrefixValid) {
     ccErrorNo = 3;
     return false; 
  }
    
  // See if the length is valid for this card
  lengths = cards[cardType].length.split(",");
  for (j=0; j<lengths.length; j++) {
    if (cardNo.length == lengths[j]) LengthValid = true;
  }
  
  // See if all is OK by seeing if the length was valid. We only check the 
  // length if all else was hunky dory.
  if (!LengthValid) {
     ccErrorNo = 4;
     return false; 
  };   
  
  // The credit card is in the required format.
  return true;
}