/*
    Module:         global validation functions
    Date:           06/17/2002
    Author:         Horia Rauta
    Description:    Keeps a centralized list of all validation functions 
                    required for all kind of form validations. Also keeps 
                    two helper functions displaying some professional looking
                    error messages.
*/

var undefined = null;

function validateDate(value) {
    var date = /^\d?\d\/\d?\d\/(\d\d)?\d\d$/;
    
    if (! date.test(value))
        return false;
    
    // Create a new date object. Year, Month and Day must be retrieved 
    // exactly as input in form. Otherwise, data is not valid

    var dt = new Date(value);
    var dtTmp = new Date(dt.getMonth() + 1 + "/" + dt.getDate() + "/" + dt.getFullYear());
    var dArray;
	
    dArray = value.split("/");
		
    var formYear = parseInt(dArray[2], 10);
    var formDay = parseInt(dArray[1], 10);
    var formMonth = parseInt(dArray[0], 10);


    if (formYear != dtTmp.getFullYear() || formMonth != dtTmp.getMonth() + 1 || formDay != dtTmp.getDate())
        return false;

    var limitDown= new Date("1/1/1900");
    var limitUp = new Date("12/31/2014");

    if (dt < limitDown || dt > limitUp)
        return false;

    // everything is OK, form input validated
    return true;
}

function validatePhone(value) {
    var phone = /^(\d|\+\d+[-\. ]?)?(\(\d+\)[-\. ]?)?(\d+[-\. ]?)+\d+$/;
    return phone.test(value);
}

function validateZIPCode(value, countryCode) {
    var zip;

    if (countryCode == 'US') {
        zip = /^\d{5}(-\d{4})?$/;
        if (! zip.test(value))
            return 1;
    } else if (countryCode == 'UK') {
        zip = /^[a-z]{1,2}[\da-z]{1,2} ?\d[a-z][a-z]$/i;
        if (! zip.test(value))
            return 2;
    } else if (countryCode == 'CA') {
        zip = /^[a-z]\d[a-z][-\. ]?\d[a-z]\d$/i;
        if (! zip.test(value)) 
            return 3;
    } else {
        return 0;
    }
    return 0;
}

function validateCCNumber(value, type) 
{
    var ccstart;
    var ccver;
    
    if (type == 'VI') 
    {
        ccstart = /^4/;
        ccver = /^\d{16}|\d{13}|\d{4}-\d{4}-\d{4}-\d{4}|\d{4} \d{4} \d{4} \d{4}$/;
    } 
    else if (type == 'MC') 
    {
        ccstart = /^5[1-5]/;
        ccver = /^\d{16}|((\d{4} ){3}|(\d{4}-){3})\d{4}$/;
    } 
    else if (type == 'AM') 
    {
        ccstart = /^3[47]/;
        ccver = /^\d{15}|\d{4}-\d{6}-\d{5}|\d{4} \d{6} \d{5}$/;
    } 
    else if (type == 'DI') 
    {
        ccstart = /^6011/;
        ccver = /^\d{16}|((\d{4} ){3}|(\d{4}-){3})\d{4}$/;
    } 
    else if (type == 'DC') 
    {
        ccstart = /^3[068]/;
        ccver = /^\d{14}$/;
    } 
    else 
    {
        ccstart = /^.*/;
        ccver = /^.*/;
    }
    
    return ccstart.test(value) && ccver.test(value);
}

function validateEmail(value) 
{
    var email = /^[\w\._-]+@([\w_-]+\.)+[\w_]+$/;
    return email.test(value);
}

function validateFloat( value )
{
    var number = /^[+-]?((\d+(\.\d+)?)|(\.\d+)|(\d+\.))$/;

    if ( value == '' )
    {
        return false;
    }

    return number.test( value );
}

function validatePositiveFloat(value) 
{
    var number = /^((\d+(\.\d+)?)|(\.\d+)|(\d+\.))$/;
    return number.test(value);
}

function validateInteger(value) 
{
    var number = /^[+-]?\d+$/;
    return number.test(value);
}

function validatePositiveInteger(value) 
{
    var number = /^\d+$/;
    return number.test(value);
}

function validateTextArea(value, maxLength) 
{
    return (value.length <= maxLength);
}

var colorArray = new Array();
var fontWeightArray = new Array();

function highlightErrors(errorDivs, errorCtrl, errorString, displayName) 
{
    if (errorDivs.length == 0 && errorString == '')
        return;
        
    if (displayName == undefined) 
        displayName = "DisplayErrorID";

    // keep all the old settings
    var divs = document.getElementsByTagName( "DIV" );
    var divElem;
    
    for ( var i = 0; i < divs.length; i++ )
    {
        divElem = divs[i];

        if ( divElem.id.indexOf( "ErrorID" ) >= 0 )
        {
            colorArray[i] = divElem.style.color;
            fontWeightArray[i] = divElem.style.fontWeight;
        }
    } 

    for ( var i = 0; i < errorDivs.length; i++ ) 
    {
        divElem = document.getElementById( errorDivs[i] );
        divElem.style.color      = 'red';
        divElem.style.fontWeight = 'bold';
    }

    if ( errorCtrl != null ) 
    {
        errorCtrl.focus( );
    }

    var errorDiv = document.getElementById( displayName );
    
    errorDiv.innerHTML = errorString;
    errorDiv.style.color = 'white';
    errorDiv.style.backgroundColor = 'red';
    errorDiv.style.fontWeight = 'bold';
    errorDiv.style.fontSize = '12px';
    errorDiv.visibility = 'visible';
}

function backToBlack(displayName) 
{
    if (colorArray.length == 0)
        return;

    if (displayName == undefined)
        displayName = "DisplayErrorID";
        
    var divs = document.getElementsByTagName("DIV");
    var divElem;
    for (var i = 0; i < divs.length; i++) 
    {
        divElem = divs[i];
        if (divElem.id.indexOf("ErrorID") >= 0) 
        {
            divElem.style.color = colorArray[i];
            divElem.style.fontWeight = fontWeightArray[i];
        }
    }
    divElem = document.getElementById(displayName);
    divElem.innerHTML = "";
}

function trim(value) 
{
    if (value.charAt(0) != " " && value.charAt(value.length - 1) != " ")
        return value;

    var retValue = "";
    for (var i = 0; i < value.length; i++)
        if (value.charAt(i) != " ")
            break;

    if (i == value.length)
        return "";

    retValue = value.substring(i, value.length);

    for (i = retValue.length - 1; i >= 0; i--)
        if (retValue.charAt(i) != " ")
            break;

    retValue = retValue.substring(0, i + 1);
    return retValue;
}

function checkFormFieldsMsg(form, preChecks, postChecks, display, message) 
{
    var displayName;

    if (display == "") 
        displayName = "DisplayErrorID";
    else
        displayName = "DisplayError" + display;

    backToBlack(displayName);

    if (preChecks != null) 
        preChecks(form);

    var empty = /^\s*$/;
    var errorDivs = new Array();
    var errorCtrl = new Array(1);
    var errorReason = new Array(1);
    errorReason[0] = "";
    errorCtrl[0] = null;

    with (form) 
    {
        for (var k = elements.length - 1; k >= 0; k--) 
        {
            var e = elements[k];
            if (e.checkFor == undefined)
                continue;

            if (e.disabled)
				continue;

            if (e.type == 'text') 
            {
                e.value = trim(e.value);

                if (e.checkFor.indexOf("R") >= 0 && empty.test(e.value)) 
                {
                    assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;A value for %s is required");
                }

                if (e.checkFor.indexOf("P") >= 0 && e.value != "" && ! validatePhone(e.value)) 
                {
                    assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;The value you provided for %s is not correct");
                }

                if (e.checkFor.indexOf("M") >= 0 && e.value != "" && ! validateEmail(e.value)) 
                {
                    assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;The value you provided for %s is not correct");
                }

                if (e.checkFor.indexOf("Z") >= 0 && e.value != "") 
                {
                    if (e.countryID == undefined || empty.test(e.countryID)) 
                        e.countryID = "US";
                    var zipRes = validateZIPCode(e.value, e.countryID);
                    switch (zipRes) {
                        case 1:
                          assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;An example of US %s is: 83883 (five digits)");
                          break;
                        case 3:
                          assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;An example of Canadian %s is: X2F 3R5 (3 letters and 3 digits alternated)");
                          break;
                        case 2:
                          assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;Some examples of UK %s are: AA0 3FC or AB01 4RF or L1 2DF or L22 9HK or LKJ 4GV");
                          break;
                    }
                }

                if (e.checkFor.indexOf("D") >= 0 && e.value != "" && ! validateDate(e.value)) 
                {
                    assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;The value you provided for %s is not correct or is out of range");
                }

                if (e.checkFor.indexOf("C") >= 0 && e.value != "") 
                {
                    if (e.cardID == undefined || empty.test(e.cardID))
                        e.cardID = "VI";
                    if (! validateCCNumber(e.value, e.cardID))
                        assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;The number you provided for %s is not correct");
                }

                if (e.checkFor.indexOf("N") >= 0 && e.value != "") 
                {
                    if (e.checkFor.indexOf("+") >= 0 && ! validatePositiveInteger(e.value) ||
                        e.checkFor.indexOf("A") >= 0 && ! validateInteger(e.value)) 
                    {
                        assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;The number you provided for %s is not correct");
                    }
                }

                if (e.checkFor.indexOf("F") >= 0 && e.value != "") 
                {
                    if (e.checkFor.indexOf("+") >= 0 && ! validatePositiveFloat(e.value) ||
                        e.checkFor.indexOf("A") >= 0 && ! validateFloat(e.value)) 
                    {
                        assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;The number you provided for %s is not correct");
                    }
                }
            } 
            else if (e.type == 'textarea') 
            {
                if (e.checkFor.indexOf("R") >= 0 && empty.test(e.value)) 
                {
                    assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;A value for %s is required");
                }
                 
                if (e.maxLength == undefined)
                    continue;

                if (e.value.length > e.maxLength) 
                {
                    assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;The length of the text for %s exceeds the maximum allowed");
                }
            } 
            else if (e.type == 'password') 
            {
                if (e.checkFor.indexOf("R") >= 0 && empty.test(e.value)) 
                {
                    assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;A value for %s is required");
                }
            } 
            else if (e.type == 'radio') 
            {
                // nothing for now
            } 
            else if (e.options) 
            {
                if (e.checkFor == "R") 
                {
                    if (e.notSelected == undefined || e.notSelected == "")
                        e.notSelected = -1;

                    if (e.notSelected == e.selectedIndex) 
                    {
                        assignError(errorDivs, errorCtrl, errorReason, e, "&nbsp;An option must be selected for %s");
                    }
                }
            } 
        } // for

        var defMsg = "&nbsp;Please provide correct values in all the fields displayed in RED";

        if (postChecks != null) 
        {
            newErrors = postChecks(form, "");
            addErrors(newErrors, errorDivs, errorCtrl, errorReason);
        }

        var msg;

        if (message  == undefined || message == "")
            msg = createErrorMsg(errorDivs, errorReason, defMsg);
        else
            msg = message;
            
        if (errorDivs.length == 0)
            return true;
        else 
        {
            highlightErrors(errorDivs, errorCtrl[0], msg, displayName);
            return false;
        }
    } // with
}

function checkFormFields(form, preChecks, postChecks) 
{
    return checkFormFieldsMsg(form, preChecks, postChecks, "", "");
}

function checkNamedFormFields(form, preChecks, postChecks, display) 
{
    return checkFormFieldsMsg(form, preChecks, postChecks, display, "");
}

function validFormMessage(form, preChecks, postChecks, submitFnc, display, message) {
    if (checkFormFieldsMsg(form, preChecks, postChecks, display, message))
    {
        submitFnc();
        return true;
    }
    
    return false;
}

function validForm(form, preChecks, postChecks, submitFnc) 
{
    return validFormMessage(form, preChecks, postChecks, submitFnc, "", "");
}

function validNamedForm(form, preChecks, postChecks, submitFnc, display) {
    validFormMessage(form, preChecks, postChecks, submitFnc, display, "");
}

function assignError(errorDivs, errorCtrl, errorReason, err, reason) {
    var l = errorDivs.length;
    errorDivs[l] = err.errorID;
    errorCtrl[0] = err;
    errorReason[0] += reason.replace(/%s/, 
            (err.errorLabel == undefined ? err.name: err.errorLabel)) + "\n";
}

function createErrorMsg(errorDivs, errorReason, defMsg) {
    if (errorDivs.length > 2 || errorDivs.length == 0)
        return defMsg;
    
    if (errorDivs.length == 1)
        return errorReason[0];

    var msgs = errorReason[0].split("\n");
    return msgs[0] + "<br>" + msgs[1];
}

function addErrors(newErrors, errorDivs, errorCtrl, errorReason) {
    if (newErrors.currIndex == 0)
        return;
    
    var k;
    for (k = errorDivs.length - 1; k >= 0; k--) {
        errorDivs[k + newErrors.currIndex] = errorDivs[k];
    }

    for (k = 0; k < newErrors.currIndex; k++) {
        var err = newErrors.errorCtrls[k];
        errorDivs[k] = err.errorID;
        if (errorCtrl[0] == null) {
            errorCtrl[0] = err;
        }
        errorReason[0] += newErrors.errorMsgs[k].replace(/%s/, 
            (err.errorLabel == undefined ? err.name: err.errorLabel)) + "\n";
    }
}

function ErrorObject() {
    this.errorCtrls = new Array(0);
    this.errorMsgs = new Array(0);
    this.currIndex = 0;
    this.addError = memberAddError;
}

function memberAddError(e, msg) {
    this.errorCtrls[this.currIndex] = e;
    this.errorMsgs[this.currIndex] = msg;
    this.currIndex++;
}
