/*
 * ClientSideValidation Framework
 *
 * Distributable under LGPL.
 * See terms of license at opensource.org
 *
 * Dependent on cross browser library (see www.cross-browser.org) and
 * clientValidation.js file.
 *
 * Author: Matt Baldree
 * Date: 2-22-03
 */

///////////////////////// validate form helper funcitons ///////////////////////////////////////////////

/*
 * check for restraint.Checks to see if form input is valid. It looks for
 * id's with 'r???_??'. 'r' may be optional.
 *
 * el - element to check
 * regExp - regular expression
 * errMsg - error message to attach
 * fxName - function to use to perform check
 *
 * returns ValidationError object if an error is discoverd
 */
function csvCheckFx(el, chkfx) {
    if (!el) return;

    if (!csvIsNullOrSpace(el.id) && chkfx.regExp.test(el.id)) {
        var tmpFx = chkfx.fxName+'("'+String.trim(el.value)+'")';
        if (!eval(tmpFx)) {
            return new ValidationError(el, chkfx.errMsg);
        }
    }
    return null;
}


/*
 * Checks to see if form input is requied. It looks for
 * id's with 'r??_??'
 *
 * returns ValidationError object if an error is discoverd
 */
function csvCheckRequired(el) {
    if (!el) return;

	var filter = /^r[a-zA-Z0-9]*_/;
    if (!csvIsNullOrSpace(el.id) && filter.test(el.id)) {
        if (csvIsNullOrSpace(String.trim(el.value))) {
            return new ValidationError(el, 'A value is required');
        }
    }
    return null;
}

/*
 * Checks to see if form input is requied. It looks for
 * id's with 'r??_??'
 *
 * returns true if required
 */
function csvIsRequired(el) {
    if (!el) return;

	var filter = /^r[a-zA-Z0-9]*_/;
    if (!csvIsNullOrSpace(el.id) && filter.test(el.id)) {
        return true;
    } else
        return false;
}


/*
 * return meta information in a string form
 * id=''
 * value=''
 */
function csvElementMetaInfo(el) {
    if (!el) return;
    return('id='+el.id+'\nvalue='+el.value);
}

///////////////////////// display helper funcitons ///////////////////////////////////////////////
/*
 * format string for display in error message box. Note, that the prefix
 * including the prefix delimiter are assumed to removed before handed to
 * tis function.
 *
 * The rules are:
 * 1. If string contains '_' or '.', then the string will have this token replaced with spaces.
 * 2. If string contains a number, all lower or upper case, or non word then return as is. We cannot
 * tell where to break it.
 * 3. Treat string as a mix case.
 *
 */
function csvFormatLabelForDisplay(str) {
    if (str==null) return '';

    //contains '_'
    var filter = /_/;
    if (filter.test(str)) {
        while (filter.test(str)){
            str = str.replace(/_/,' ');
        }
        return str;
    }

    //contains '.'
    var filter = /\./;
    if (filter.test(str)) {
        while (filter.test(str)){
            str = str.replace(/\./,' ');
        }
        return str;
    }

    //lower or all upper case
    filter = /^(?:[a-z]+|[A-Z]+)$/;
    if (filter.test(str)) {
        return str;
    }


    //mix case
    filter = /[A-Z][a-z]+[A-Z]/;
    if (filter.test(str)) {
        while (filter.test(str)) {
            str = str.replace(/([A-Z][a-z]+)([A-Z])/, '$1 $2');
        }
        return str;
    }

    return str;
}


/*
 * determines the number of columns to display for error box
 */
function csvGetDisplayErrorColumns() {
    var el = cbeGetElementById(csvValidationErrorMessageMarker);
    if (el) {
        var width = el.cbe.width();
        return Math.round(width/csvValidationErrorColumnWidth);
    }
}


/*
 * write html to error message marker and toggle form labels and fields
 *
 * html - html to display
 * lblStyle - style you want to set on the labels
 * fldStyle - style you want to set on the fields
 */
function csvDisplayErrorMessage(html, lblStyle, fldStyle) {
    //write message
    if (html) {
        var el = cbeGetElementById(csvValidationErrorMessageMarker);
        if (el) {
            el.cbe.innerHtml(html);
        }
    }
    //change label and element class name
    if (csvValidationErrors) {
        for (i=0; i<csvValidationErrors.length; i++) {
            var elErr = csvValidationErrors[i];
            if (elErr) {
                //find label for error element
                var elErrLabel = cbeGetElementById(elErr.label());
                if (elErrLabel) {
                    elErrLabel.className = lblStyle;
                } else {
                    if (csvValidationDebug) alert('Unable to find error label for '+elErr.label());
                }
                elErr.element.className = fldStyle;
            }
        }
    }
}


///////////////////////// restraint functions /////////////////////////////////////////////

/*
 * helper functions used by clienside validation and others
 *
 */
var csvDateField;

/*
 * Is string null or contains only spaces.
 *
 * str - string to check
 */
function csvIsNullOrSpace(str) {
    if (str==null)
        return true;
    else if (str.length=0 || str=='')
			return true;
	else {
		var filter = /^\s+$/;
        return filter.test(str);
	}
}

/*
 * String has at least n characters. If str or length is null,
 * then function will return false. If str is not alpha or space,
 * then function will return false. If str is null or space,
 * then function will return false.
 *
 * str - string to check
 * len - total characters checking for
 */
function csvIsAtLeastNChars(str,len) {
    if (str==null || len==null)
        return false;

    if (!isAlphaSpace(str))
    	return false;

    if (csvIsNullOrSpace(str))
    	return false;

	if (str.length < len)
	    return false;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * String is a valid SSN. It allows for 3-2-4 or just
 * 9 integers.
 *
 * str - string to check
 */
function csvIsSSN(str)
{
	var filter = /^[0-9]{3}-[0-9]{2}-[0-9]{4}$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
		return true;

	filter = /^[0-9]{9}$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
		return true;

    else
        return csvIsNullOrSpace(str);
}

/*
 * String is alpha
 *
 * str - string to check
 */
function csvIsAlpha(str)
{
	var filter = /^[a-zA-Z]+$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
	    return true;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * String is alpha and space is allowed.
 *
 * str - string to check
 */
function csvIsAlphaSpace(str)
{
	if (csvIsNullOrSpace(str))
		return false;

	var filter = /^[a-zA-Z ]+$/;
	if (filter.test(str))
	    return true;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * String is a valid email
 *
 * str - string to check
 */
function csvIsEmail(str)
{
    var filter=/^([\w]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,3}(?:\.[a-z]{2})?)$/i
    if (!csvIsNullOrSpace(str) && filter.test(str))
        return true;
    else
        return csvIsNullOrSpace(str);
}


/*
 * Is string a real?
 *
 * str - string to check
 */
function csvIsReal(str)
{
	var filter = /^-?\d*\.?\d{1,2}$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
	    return true;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * Is string a money?
 *
 * str - string to check
 */
function csvIsMoney(str)
{
    var filter = /^(\d*\.\d{1,2}|\d\.)?$/;
    if (!csvIsNullOrSpace(str) && filter.test(str))
        return true;
    else
        return csvIsNullOrSpace(str);
}

/*
 * Is string an integer?
 *
 * str - string to check
 */
function csvIsInteger(str)
{
	var filter = /^\d+$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
	    return true;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * Is string a non-zero integer
 *
 * str - string to check
 */
function csvIsNonZeroInteger(str)
{
	var filter = /^[1-9]+$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
	    return true;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * Is string a valid zip?
 *
 * str - string to check
 */
function csvIsZip(str)
{
	var filter = /^[0-9]{5}(-[0-9]{4})?$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
	    return true;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * Is string a valid date of birth?
 *
 * str - string to check
 */
function csvIsDateOfBirth(str)
{
	if (csvIsNullOrSpace(str))
		return true;

	if(csvIsDate(str))
	{
		if (Date.parse(new Date().toUTCString())< Date.parse(csvDateField))
			return false;
		else
			return true;
	}
	else
		return false;
}

/*
 * Is string a valid date? It supports the following formats:
 * mm-dd-yyyy, mm/dd/yyyy, mm.dd.yyyy, mm dd yyyy,
 * mmddyyyy, m-d-yyyy, m/d/yyyy, m.d.yyyy,
 * m d yyyy, m-d-yy, m/d/yy, m.d.yy, m d yy,
 * (yy is 20yy)
 *
 * str - string to check
 */
function csvIsDate(str)
{
	if (csvIsNullOrSpace(str))
		return true;

	var strDatestyle = "US"; //United States date style
	//var strDatestyle = "EU";  //European date style
	var strDateArray;
	var strDay;
	var strMonth;
	var strYear;
	var intday;
	var intMonth;
	var intYear;
	var booFound = false;
	var strSeparatorArray = new Array("-"," ","/",".");
	var intElementNr;

	//if a separator is found then separate into parts
	for (intElementNr = 0; intElementNr < strSeparatorArray.length; intElementNr++) {
		if (str.indexOf(strSeparatorArray[intElementNr]) != -1) {
			strDateArray = str.split(strSeparatorArray[intElementNr]);
			if (strDateArray.length != 3) {
				return false;
			}
			else {
				strDay = strDateArray[0];
				strMonth = strDateArray[1];
				strYear = strDateArray[2];
			}
			booFound = true;
	   }
	}

	//if no separator
	if (booFound == false) {
		if (str.length>5) {
			strDay = str.substr(0, 2);
			strMonth = str.substr(2, 2);
			strYear = str.substr(4);
	   }
	   else
	   	return false;
	}

	//if abbreviated year
	if (strYear.length == 2) {
		strYear = '20' + strYear;
	}

	// US style
	if (strDatestyle == "US") {
		strTemp = strDay;
		strDay = strMonth;
		strMonth = strTemp;
	}

	//valid day?
	intday = parseInt(strDay, 10);
	if (!csvIsInteger(strDay) || intday<1) {
		return false;
	}

	//valid year?
	intYear = parseInt(strYear, 10);
	if (!csvIsInteger(strYear) || intYear<1) {
		return false;
	}


	//valid month?
	intMonth = parseInt(strMonth, 10);
	if (!csvIsInteger(strMonth) || intMonth<1 || intMonth>12) {
		return false;
	}

	//check for valid day given month
	if ((intMonth == 1 || intMonth == 3 || intMonth == 5 || intMonth == 7 || intMonth == 8 ||
		intMonth == 10 || intMonth == 12) && (intday > 31)) {
		return false;
	}
	if ((intMonth == 4 || intMonth == 6 || intMonth == 9 || intMonth == 11) && (intday > 30)) {
		return false;
	}
	if (intMonth == 2) { //feb - leap year check
		if (intday < 1) {
			return false;
		}
		if (csvIsLeapYear(intYear) == true) {
			if (intday > 29) {
				return false;
			}
		}
		else {
			if (intday > 28) {
				return false;
			}
		}
	}

	csvDateField = intMonth + "/" + intday+"/" + strYear;
	return true;
}

/*
 * Is year a leap year?
 *
 * intYear - year to check
 */
function csvIsLeapYear(intYear) {
	if (intYear % 100 == 0) {
		if (intYear % 400 == 0) { return true; }
	}
	else {
		if ((intYear % 4) == 0) { return true; }
	}
	return false;
}


/*
 * Is string a valid time?
 *
 * str - string to check
 */
function csvIsTime(str)
{
	if (csvIsNullOrSpace(str))
		return true;

	var pattern = /^(\d{1,2})\s*(:\s*\d{1,2})?\s*(:\s*\d{1,2})?\s*(AM|am|PM|pm)?$/;

	var matchArray = str.match(pattern);
	if (matchArray == null) {
		return false;
	}

	var hour = matchArray[1];
	var minu
	te = matchArray[2];
	var second = matchArray[3];
	var ampm = matchArray[4];

	if (second=="") { second = null; }
	if (ampm=="") { ampm = null }

	if (hour < 0  || hour > 23) {
		return false;
	}

	if  (hour > 12 && ampm != null) {
		return false;
	}

	if (minute<0 || minute > 59) {
		return false;
	}

	if (second != null && (second < 0 || second > 59)) {
		return false;
	}
	return true;
}

/*
 * Is string alpha or numberic?
 *
 * str - string to check
 */
function csvIsAlphaNum(str)
{
	var filter = /^[a-zA-Z0-9]+$/;
	if (!csvIsNullOrSpace(str) && filter.test(str))
	    return true;
	else
	    return csvIsNullOrSpace(str);
}

/*
 * Add number of days to a date
 *
 * dt - a date. This string will be fed to the Date() ctr.
 * dys - number of days to add to date
 */
function csvDateAddDays(dt,dys)
{
	delim = "/";
	dt = new Date(dt);
	dt.setDate(dt.getDate() + Number(dys));
	dtstr=(dt.getMonth()+1)+delim+dt.getDate()+delim+dt.getYear()
	return(dtstr);
}

/*
 * Add months to a date
 *
 * dt - a date. This string will be fed to the Date() ctr.
 * mnths - number of months to add to date
 */
function csvDateAddMonths(dt,mnths)
{
	delim = "/";
	dt = new Date(dt);
	dt.setMonth(dt.getMonth() + Number(mnths));
	dtstr=(dt.getMonth()+1)+delim+dt.getDate()+delim+dt.getYear()
	return(dtstr);
}

/*
 * Determine number of days between dates. Negative days means the
 * first date was after the second date.
 *
 * dt1 - first date
 * dt2 - second date
 */
function csvDateDiffDays(dt1,dt2)
{
	dt1 = new Date(dt1);
	dt2 = new Date(dt2);
	dt = dt1 - dt2;
	return(dt/60/60/24/1000);
}


/*
 * String trim functions. These functions extend string so
 * you can use them on any string.
 */

/*
 * Trim left side of string.
 */
function String_ltrim(str)
{
    if (str)
        return str.replace(/^\s+/,'');
    else
        return '';
}

/*
 * Trim right side of string.
 */
function String_rtrim(str)
{
    if (str)
        return str.replace(/\s+$/,'');
    else
        return '';
}

/*
 * Trim both left and right side of string.
 */
function String_trim(str){
    if (str)
        return String.rtrim(String.ltrim(str));
    else
        return '';
}

String.trim = String_trim;
String.ltrim = String_ltrim;
String.rtrim = String_rtrim;

