/**
 * Define the namespace for form validation
 */
 function FormValidation()
 {
 }
 
 /**
  * Regexp to test for a blank field
  */
 FormValidation.emptyString = /^\s*$/;

/**
 * Retrieves an element given a name or an id.  If the element does not have
 * an id, it checks for a name.
 * @param elementId the id of the element to look for
 */
FormValidation.getElementByNameOrId = function(elementId)
{
	var ele = document.getElementById(elementId);
	if (ele === null)
	{
		var eles = document.getElementsByName(elementId);
		if (eles.length > 0)
		{
			ele = eles[0];
		}
	}
	return ele;
};

/**
 * Simply checks for blanks. A very basic, first pass interpretation of "required"
 * @param validationFields the ids of the form elementsto validate. The expected 
 * format of each item is a map of the form {'label':'string','elementId':'theElementId'}
 * @return false if validation failed, true if successful
 */
FormValidation.requiredValidator = function(validationFields) 
{
    for (var i in validationFields) 
    {
        var each = validationFields[i];
        var ele = FormValidation.getElementByNameOrId(each['elementId']);
        if (ele === null) {continue;}
        if (FormValidation.isBlank(ele.value))
        {
            FormValidation.selectElement(ele);
            window.alert(each['label'] + " cannot be blank, it is required.");
            return false;
        }
    }
    return true;
};

FormValidation.selectElement = function(ele)
{
	ele.focus(); 
	
	try{ele.select();}catch(e){}
};

//returns true if the string contains 0-9 and nothing else
FormValidation.isNumericOnly = function(input) 
{
	return input.match(/[^0-9]+/) === null;
};

FormValidation.validateNumeric = function(elementId, label)
{
	var ele = FormValidation.getElementByNameOrId(elementId);
	var errorMessage = "";
	if (!FormValidation.isNumericOnly(ele.value))
	{
		errorMessage = label + " must contain numbers only.";
	}
	
	return FormValidation.displayErrorMsg(errorMessage, ele);
};

//returns true if the string is truly blank (eg it trims off whitespace)
FormValidation.isBlank = function(input) 
{
    return FormValidation.emptyString.test(input);
};

//phone number - strip out delimiters and check for 10 digits. Returns
//blank if good.
FormValidation.checkPhone = function (strng) 
{
    var error = "";
    if (!strng) {
        error = "You didn't enter a phone number.\n";
    }

    var stripped = strng.replace(/[\(\)\.\-\ ]/g, ''); //strip out acceptable non-numeric characters
    if (isNaN(parseInt(stripped))) {
        error = "The phone number contains illegal characters.";

    }
    
    if (!(stripped.length == 10)) {
        error = "The phone number is the wrong length. Make sure you included an area code.\n";
    }
    
    return error;
};

/**
 * Displays an error message if one has occurred.
 * @param errorMsg the error message to displya
 * @param ele the element the error is coming from
 * @return true if no error, false otherwise
 */
FormValidation.displayErrorMsg = function(errorMsg, ele)
{
    if (!errorMsg)
    {
        return true;
    }
    else
    {
        ele.focus();
        ele.select();
        window.alert(errorMsg);
        return false;
    }
};

/**
 * validate a text input to ensure it has a proper phone number. Designed to work in onSubmit
 * @param eleId the id of the input element to validate
 * @return true if the element has a valid phone number, false otherwise
 */
FormValidation.validatePhoneByEleId = function(eleId)
{
    var ele = FormValidation.getElementByNameOrId(eleId);
    var retVal = FormValidation.checkPhone(ele.value);

	return FormValidation.displayErrorMsg(retVal, ele);
};

/**
 * validate a text input to ensure it has a proper email address. Designed to work in onSubmit
 * @param eleId the id of the input element to validate
 * @param requiredTld the required top level domain of the email address
 * @return true if the element has a valid phone number, false otherwise
 */
FormValidation.validateEmailByEleId = function(eleId, requiredTld)
{
    var ele = FormValidation.getElementByNameOrId(eleId);
    
    return FormValidation.validateEmailByEle(ele, requiredTld);
};

/**
 * validate a text input to ensure it has a proper email address. Designed to work in onSubmit
 * @param ele the input element to validate
 * @param requiredTld the required top level domain of the email address
 * @return true if the element has a valid email address, false otherwise
 */
FormValidation.validateEmailByEle = function(ele, requiredTld)
{
    var retVal = FormValidation.validateEmailAddress(ele.value, requiredTld);

	return FormValidation.displayErrorMsg(retVal, ele);
};

//-----------------------------------------------------------------------------
// Parses an email address to make sure that it has the proper format
//-----------------------------------------------------------------------------
FormValidation.validateEmailAddress = function(emailStr, requiredTld)
{
	// Define a counter for loops
	var i = null;
	
    var knownDomsPat = /^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
    var emailPat = /^(.+)@(.+)$/;
    var specialChars = "\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
    var validChars = "\[^\\s" + specialChars + "\]";
    var quotedUser = "(\"[^\"]*\")";
    var ipDomainPat = /^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
    var atom = validChars + '+';
    var word = "(" + atom + "|" + quotedUser + ")";
    var userPat = new RegExp("^" + word + "(\\." + word + ")*$");
    //var domainPat = new RegExp("^" + atom + "(\\." + atom +")*$");
    var matchArray = emailStr.match(emailPat);

    if (matchArray === null)
    {
        return "The email address is Invalid";
    }

    var user = matchArray[1];
    var domain = matchArray[2];
    for (i = 0; i < user.length; i++)
    {
        if (user.charCodeAt(i) > 127)
        {
            return "The email address's user name contains invalid characters.";
        }
    }

    for (i = 0; i < domain.length; i++)
    {
        if (domain.charCodeAt(i) > 127)
        {
            return "The email address's domain name contains invalid characters.";
        }
    }

    if (user.match(userPat) === null)
    {
        return "The email address's user name is invalid.";
    }

    var IPArray = domain.match(ipDomainPat);
    if (IPArray !== null)
    {
        for (i = 1; i <= 4; i++)
        {
            if (IPArray[i]>255)
            {
                return "The Destination IP Address is invalid.";
            }
        }
        return true;
    }

    var atomPat = new RegExp("^" + atom + "$");
    var domArr = domain.split(".");
    var len = domArr.length;
    for (i = 0; i < len; i++)
    {
        if (domArr[i].search(atomPat)==-1)
        {
            return "The email address's domain name is invalid.";
        }
    }
    
    var tld = domArr[domArr.length-1];
    
    if (requiredTld && requiredTld != tld)
    {
    	return "The email address is required to end in " + requiredTld + ".";
    }

    if (tld.length != 2 && tld.search(knownDomsPat)==-1)
    {
        return "The email address's domain name extension is invalid";
    }

    if (len < 2)
    {
        return "The email address is missing a hostname.";
    }

    return "";
};

/**
 * Returns true if one of a group of radio buttons is checked.
 * @param elementId the name of the radio elements
 * @return true, if checked, false if not
 */
FormValidation.validateRadioGroup = function(elementId, label)
{
	var radioEles = document.getElementsByName(elementId);
	var isChecked = false;
	for (var i = 0; i < radioEles.length && !isChecked; ++i)
	{
		isChecked = radioEles[i].checked;
	}

	var errorMessage = "";
	if (!isChecked)
	{
		errorMessage = "Please select a " + label + " before proceeding.";
	}
	
	return FormValidation.displayErrorMsg(errorMessage, radioEles[0]);
};

FormValidation.compareElementValues = function(eleId1, eleId2, label)
{
	var ele1 = FormValidation.getElementByNameOrId(eleId1);
	var ele2 = FormValidation.getElementByNameOrId(eleId2);
	
	var errorMessage = "";
	if (ele1.value != ele2.value)
	{
		errorMessage = "The two values of " + label + " do not match.";
	}
	return FormValidation.displayErrorMsg(errorMessage, ele1);
};
