/**
* ValidationUtils is a class used to perform form validation.  Seceral of its
* methods return boolean values and can be used in the onsubmit handler of forms
* @namespace ValidationUtils
* @class ValidationUtils
* @constructor
* @author patrick@deepwebtech.com
*/
function ValidationUtils()
{
    ValidationUtils.errorMsg = "<<uninitialized>>";
    ValidationUtils.requiredFields = "<<uninitialized>>";
    ValidationUtils.requiredFieldsHtml1 = "<<uninitialized>>";
    ValidationUtils.requiredFieldsHtml2 = "<<uninitialized>>";
    ValidationUtils.noPhone = "<<uninitialized>>";
    ValidationUtils.illegalPhoneChars = "<<uninitialized>>";
    ValidationUtils.phoneWrongLength = "<<uninitialized>>";
    ValidationUtils.requiredElement = "<<uninitialized>>";
    ValidationUtils.requiredElement2 = "<<uninitialized>>";
    ValidationUtils.blankEmail = "<<uninitialized>>";
    ValidationUtils.invalidEmail = "<<uninitialized>>";
    ValidationUtils.emailUserBadChars = "<<uninitialized>>";
    ValidationUtils.emailDomBadChars = "<<uninitialized>>";
    ValidationUtils.emailUserInvalid = "<<uninitialized>>";
    ValidationUtils.destIpInvalid = "<<uninitialized>>";
    ValidationUtils.domNameInvalid = "<<uninitialized>>";
    ValidationUtils.domNameExtInvalid = "<<uninitialized>>";
    ValidationUtils.emailMissingHost = "<<uninitialized>>";
    ValidationUtils.blankSearchField = "<<uninitialized>>";
    ValidationUtils.invalidSearchParam = "<<uninitialized>>";
    ValidationUtils.atLeastOne = "<<uninitialized>>";
    ValidationUtils.nameLbl = "<<uninitialized>>";
    ValidationUtils.titleLbl ="<<uninitialized>>";
}

/**
 * Defines the fields to validate.  The tag files used to place form controls on
 * the pages will add id's to validate this global var. The expected format of
 * each item is an object of the form {'label':'string','elementId':'theElementId'}
 */
ValidationUtils.validationFields = [];

/**
 * Displays an error message box for a particular field that failed validation
 * @param {Object} ele the element that will receive the focus when the message
 * box is closed
 * @param {String} errorString
 * @param {String} errorTitle
 */
ValidationUtils.displayError = function(ele, errorString, errorTitle)
{
    var okFunction = function(element)
    {
        return function()
        {
            element.focus();
            try {element.select();} catch(e){}
        };
    }(ele);

    if (!errorTitle)
    {
        errorTitle = ValidationUtils.errorMsg;
    }

    MessageBox.error(errorTitle, errorString, null, okFunction);
};

/**
 * Does a first pass for determining if required fields have been filled in
 * @return {boolean} true if the required fields have been filled in.
 */
ValidationUtils.requiredValidator = function()
{
    if(ValidationUtils.validationFields.length > 0)
    {
        var fieldList = "" ;
        for (var i = 0; i < ValidationUtils.validationFields.length; ++i)
        {
            var field = ValidationUtils.validationFields[i];
            var ele = document.getElementById(field.elementId);
            if (ele.value === "")
            {
                fieldList = fieldList + ValidationUtils.requiredFieldsHtml1 + field.label + ValidationUtils.requiredFieldsHtml2;
            }
        }

        if (fieldList !== "")
        {
            ValidationUtils.displayError(ValidationUtils.errorMsg, ValidationUtils.requiredFields + fieldList);
            return false;
        }

    }

    return true;
};

/**
 * Returns true if the string contains 0-9 and nothing else
 * @param {String} input the value to verify
 * @return {boolean} true if the string is all numbers
 */
ValidationUtils.isNumeric = function(input)
{
    return input.match(/[^0-9]+/) === null;
};


/**
 * Returns true if the string is truly blank (eg: it trims off whitespace)
 * @param {String} input the value to check.
 * @return {boolean} true if the value is blank
 */
ValidationUtils.isBlank = function(input)
{
    // regexp for empty field expression test.
    var emptyString = /^\s*$/;

    if (typeof input == "undefined")
    {
        return true;
    }
    else if (input === null)
    {
        return true;
    }
    else
    {
        return emptyString.test(input);
    }
};


/**
 * Validated a phone number - strip out delimiters and check for 10 digits.
 * @param {String} phoneNumber the phone number to check
 * @return {String} an error message, if invalid, a blank otherwise
 */
ValidationUtils.checkPhone = function(phoneNumber)
{
    var error = "";
    if (ValidationUtils.isBlank(phoneNumber))
    {
        error = ValidationUtils.noPhone;
    }
    else
    {
        var stripped = phoneNumber.replace(/[\(\)\.\-\ ]/g, ''); //strip out acceptable non-numeric characters
        if (isNaN(parseInt(stripped, 10)))
        {
            error = ValidationUtils.illegalPhoneChars;
        }
        else if (!(stripped.length == 10))
        {
            error = ValidationUtils.phoneWrongLength;
        }
    }

    return error;
};

ValidationUtils.validateListPicker = function(listPickerInstance, listPickerName)
{
    var ret = true;

    if (listPickerInstance.getSelectedValues().length === 0)
    {
        ValidationUtils.displayError(ListPicker.instances.collectionCodes.availableOptions,
                ValidationUtils.atLeastOne + listPickerName, ValidationUtils.errorMsg);
        ret = false;
    }

    return ret;
};


/**
 * Validate a text input to ensure it has a proper phone number
 * @param {String} eleId the id of the input element to validate
 * @return {boolean} true if the element has a valid phone number
 */
ValidationUtils.validatePhoneByEleId = function(eleId)
{
    var ele = document.getElementById(eleId);
    var retVal = ValidationUtils.checkPhone(ele.value);

    if (retVal === "")
    {
        return true;
    }
    else
    {
        ValidationUtils.displayError(ele, retVal);
        return false;
    }
};

/**
 * Validate the text input to ensure it has a value
 * @param {String} eleId the id of the input element to validate
 * @param {Sring} elementName a human-readable description of the value tested
 * @return {boolean} true if the element has a value that is not blank.
 */
ValidationUtils.validateRequiredElement = function(eleId, elementName)
{
    var ele = document.getElementById(eleId);
    if (ValidationUtils.isBlank(ele.value))
    {
        ValidationUtils.displayError(ele, ValidationUtils.requiredElement + " " + elementName + " " + ValidationUtils.requiredElement2);
        return false;
    }
    else
    {
        return true;
    }
};

/**
 * Parses an email address to make sure that it has the proper format
 * @param {String} emailStr the email address to parse
 * @return {String} an error message, if invalid, a blank otherwise
 */
ValidationUtils.validateEmailAddress = function(emailStr)
{
    if (emailStr === "")
    {
        return "";
    }

    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);
    var i;

    if (matchArray === null)
    {
        return ValidationUtils.invalidEmail;
    }

    var user = matchArray[1];
    var domain = matchArray[2];
    for (i = 0; i < user.length; i++)
    {
        if (user.charCodeAt(i) > 127)
        {
            return ValidationUtils.emailUserBadChars;
        }
    }

    for (i = 0; i < domain.length; i++)
    {
        if (domain.charCodeAt(i) > 127)
        {
            return ValidationUtils.emailDomBadChars;
        }
    }

    if (user.match(userPat) === null)
    {
        return ValidationUtils.emailUserInvalid;
    }

    var IPArray = domain.match(ipDomainPat);
    if (IPArray !== null)
    {
        for (i = 1; i <= 4; i++)
        {
            if (IPArray[i] > 255)
            {
                return ValidationUtils.destIpInvalid;
            }
        }
        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 ValidationUtils.domNameInvalid;
        }
    }

    if (domArr[domArr.length - 1].length != 2 && domArr[domArr.length - 1].search(knownDomsPat) == -1)
    {
        return ValidationUtils.domNameExtInvalid;
    }

    if (len < 2)
    {
        return ValidationUtils.emailMissingHost;
    }

    return "";
};

/**
 * Validate a text input to ensure it has a proper email address. Designed to work in onSubmit
 * @param {String} eleId the id of the input element to validate
 * @return {boolean} true if the element has a email address
 */
ValidationUtils.validateEmailByEleId = function(eleId)
{
    var ele = document.getElementById(eleId);
    var retVal = ValidationUtils.validateEmailAddress(ele.value);

    if (retVal === "")
    {
        return true;
    }
    else
    {
        ValidationUtils.displayError(ele, retVal);
        return false;
    }
};

/**
 * Validates the single field in a simple search box
 * @param {String} requiredElementId the id of the single field that would contain
 * the term to search for.
 * @return {boolean} true if the field contains text
 */
ValidationUtils.validateSimpleSearch = function(requiredElementId)
{
    var simpleSearchInput = document.getElementById(requiredElementId);

    if (ValidationUtils.isBlank(simpleSearchInput.value))
    {
        ValidationUtils.displayError(simpleSearchInput, ValidationUtils.blankSearchField, ValidationUtils.invalidSearchParam);
        return false;
    }
    else
    {
        return true;
    }
};

/** 
 * Validates input for search-builder template names
 * @param {String} eleVal current template name entered into create template box.
 * @param {String} title this is the title of the template.
 * @param {String} msg the message returned upon invalid input.
 * @return {boolean} true if input text satisfies validation.
 */

ValidationUtils.validateTemplateName = function(eleVal, title, msg)
{
    //Checks for alphanumeric, '-', '_', and spaces. Also accounts for l10n and i18n
    var alphaNumRegex = /^[-A-Za-z0-9\uooCo-\u1FFF\u28oo-\uFFFD_ ]+$/;

    if (eleVal.match(alphaNumRegex) === null)
    {

       MessageBox.warning(title, msg);
       return false;

    }

    return true;
};
