/* Niagara College User Interface for CAS
*  Custom form validator and submission module
*/

var submitted = false;

function ncUI_ValidateForm()
{
	return true;
}

function ncUI_TaxFactorInvert()
{
	return 1 / ncUI_TaxFactor();
}

/* Taxes[0] and Taxes[1] come from the DocTemplateTag */
function ncUI_TaxFactor()
{
	return 1 + Taxes[0].Factor + Taxes[1].Factor;
}

function ncUI_SubmitForm(paramAction)
{
	if (ncUI_ValidateForm() == true)
	{
		if (this.submitted == false)
		{
			this.submitted = true;

			document.forms[0].action = paramAction;
			document.forms[0].submit();
		}
	}
}

function ncUI_SubmitFormMethod(paramAction, paramMethod)
{
	if (ncUI_ValidateForm() == true)
	{
		if (this.submitted == false)
		{
			this.submitted = true;

			document.forms[0].method = paramMethod;
			document.forms[0].action = paramAction;
			document.forms[0].submit();
		}
	}
}

var dtCh= "-";
var minYear=1900;
var maxYear=2100;

function isInteger(s)
{
	var i;
	for (i = 0; i < s.length; i++)
	{
		/* Check that current character is number. */
		var c = s.charAt(i);

		if (((c < "0") || (c > "9")))
			return false;
	}

	return true;
}

function stripCharsInBag(s, bag)
{
	var i;
	var returnString = "";

	/* Search through string's characters one by one.
	*  If character is not in bag, append to returnString. */
	for (i = 0; i < s.length; i++)
	{
		var c = s.charAt(i);

		if (bag.indexOf(c) == -1)
			returnString += c;
	}

	return returnString;
}

function daysInFebruary (year)
{
	/* February has 29 days in any year evenly divisible by four,
	*  EXCEPT for centurial years which are not also divisible by 400 */
	return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
}

function DaysArray(n)
{
	var i;

	for (i = 1; i <= n; i++)
	{
		this[i] = 31;

		if (i == 4 || i == 6 || i == 9 || i == 11)
			this[i] = 30

		if (i == 2)
			this[i] = 29;
	}

	return this;
}

/**
*  Tests DOM Object attribute "value" for not null, identified by "id".
*  Indicates failure message msgFailure.
*
*  @param	id		ID of the DOM Object to test
*  @param	msgFailure	Message to be displayed to the user in case of failure
*  @return	msgFailure if there was a failure, null if otherwise.
*/
function ncUI_ValueCheckNotNull(id, msgFailure)
{
	if (document.getElementById(id).value == "")
	{
		if (document.getElementById(id).type != "hidden")
			document.getElementById(id).focus();

		return msgFailure;
	}
	return "";
}

function ncUI_ValueCheckIsNumeric(id, msgFailure)
{
	if (document.getElementById(id).value == "")
	{
		document.getElementById(id).focus();
		return msgFailure;
	}
	else if (isInteger(document.getElementById(id).value) == false)
	{
		document.getElementById(id).focus();
		return msgFailure;
	}
	return "";
}

function ncUI_ValueCheckIsCurrency(id, msgFailure)
{
	if (document.getElementById(id).value == "")
	{
		document.getElementById(id).focus();
		return msgFailure;
	}
	else if (ncUI_IsCurrency(document.getElementById(id).value) == false)
	{
		document.getElementById(id).focus();
		return msgFailure;
	}

	return "";
}

function ncUI_ValueCheckSelected(id, msgFailure)
{
	var x = document.getElementById(id);
	if ((x.selectedIndex == -1) || (x.options[x.selectedIndex].value == 0))
	{
		document.getElementById(id).focus();
		return msgFailure;
	}
	return "";
}

/**
*  Tests DOM Object attribute "value" to be a valid date, identified by "id".
*  Indicates failure message msgFailure.
*
*  @param	id		ID of the DOM Object to test
*  @return	Appropriate message if there was a failure, "" if otherwise.
*/
function ncUI_ValueCheckDate(id, msgFailure)
{
	var dtStr = document.getElementById(id).value;
	if (dtStr == "")
		return msgFailure;

	var daysInMonth = DaysArray(12);
	var pos1 = dtStr.indexOf(dtCh);
	var pos2 = dtStr.indexOf(dtCh, pos1 + 1);
	var strYear = dtStr.substring(0, pos1);
	var strMonth = dtStr.substring(pos1 + 1, pos2);
	var strDay = dtStr.substring(pos2 + 1);

	strYr = strYear;

	if (strDay.charAt(0) == "0" && strDay.length > 1)
		strDay = strDay.substring(1);
	if (strMonth.charAt(0) == "0" && strMonth.length > 1)
		strMonth = strMonth.substring(1);

	for (var i = 1; i <= 3; i++)
	{
		if (strYr.charAt(0) == "0" && strYr.length > 1)
			strYr = strYr.substring(1);
	}

	month = parseInt(strMonth);
	day = parseInt(strDay);
	year = parseInt(strYr);

	if (pos1 == -1 || pos2 == -1)
		return "The date format should be : yyyy-mm-dd\n";

	if (strMonth.length < 1 || month < 1 || month > 12)
		return "Please enter a valid month\n";

	if (strDay.length < 1 || day < 1 || day > 31 || (month == 2 && day > daysInFebruary(year)) || day > daysInMonth[month])
		return "Please enter a valid day\n";

	if (strYear.length != 4 || year == 0 || year < minYear || year > maxYear)
		return "Please enter a valid 4 digit year between " + minYear + " and " + maxYear + "\n";

	if (dtStr.indexOf(dtCh, pos2 + 1) != -1 || isInteger(stripCharsInBag(dtStr, dtCh)) == false)
		return "Please enter a valid date\n";

	return "";
}

/**
*  Loop through all the checkboxes on this form to ensure that at
*  least ONE of them was checked.
*  @param	myclass	Used only for the error message: "You must select one of ..."
*  @param	forwhat	Used in the error message : " for ..."
*/
function ncUI_MultiCheckValidator(myclass, forwhat)
{
	var strError = "";		/* Error Message */
	var bFound = false;		/* Check the checkboxes */
	var i = 0;			/* Loop index */
	var el;				/* Form [el]ement */

	/* Loop through all form elements and see that at least one checkbox was checked */
	for (i = 0; i < document.forms[0].elements.length; i++)
	{
		el = document.forms[0].elements[i];
		if (el.type == "checkbox")
		{
			if (el.checked == true)
			{
				bFound = true;
				break;
			}
		}
	}

	if (bFound != true)
		return "You must select at least one " + myclass + " " + forwhat + "."
	else
		return "";
}

/**
*  Tests "value" to be a valid date
*
*  @param	value		The value to check!
*  @return	The date, or null.
*/
function ncUI_toDate(value)
{
	var dtStr = value;
	if (dtStr == "")
		return null;

	var daysInMonth = DaysArray(12);
	var pos1 = dtStr.indexOf(dtCh);
	var pos2 = dtStr.indexOf(dtCh, pos1 + 1);
	var strYear = dtStr.substring(0, pos1);
	var strMonth = dtStr.substring(pos1 + 1, pos2);
	var strDay = dtStr.substring(pos2 + 1);

	strYr = strYear;

	if (strDay.charAt(0) == "0" && strDay.length > 1)
		strDay = strDay.substring(1);
	if (strMonth.charAt(0) == "0" && strMonth.length > 1)
		strMonth = strMonth.substring(1);

	for (var i = 1; i <= 3; i++)
	{
		if (strYr.charAt(0) == "0" && strYr.length > 1)
			strYr = strYr.substring(1);
	}

	month = parseInt(strMonth);
	day = parseInt(strDay);
	year = parseInt(strYr);

	if (pos1 == -1 || pos2 == -1)
		return null;

	if (strMonth.length < 1 || month < 1 || month > 12)
		return null;

	if (strDay.length < 1 || day < 1 || day > 31 || (month == 2 && day > daysInFebruary(year)) || day > daysInMonth[month])
		return null;

	if (strYear.length != 4 || year == 0 || year < minYear || year > maxYear)
		return null;

	if (dtStr.indexOf(dtCh, pos2 + 1) != -1 || isInteger(stripCharsInBag(dtStr, dtCh)) == false)
		return null;

	return new Date(year, month - 1, day, 0, 0, 0);
}

function ncUI_FormatDate(dadate)
{
	var strTemp;

	/* Format as: yyyy-mm-dd */

	/* Year */
	if (navigator.appName == "Microsoft Internet Explorer")
	{
		strTemp = (dadate.getYear()) + "-";
	}
	else
	{
		strTemp = (dadate.getYear() + 1900) + "-";
	}

	/* Month */
	if ((dadate.getMonth() + 1) < 10)
		strTemp = strTemp + "0";
	strTemp = strTemp + (dadate.getMonth() + 1) + "-";

	/* Day */
	if (dadate.getDate() < 10)
		strTemp = strTemp + "0";
	strTemp = strTemp + dadate.getDate();

	return strTemp;
}

function ncUI_FormatCurrency(num)
{
	num = num.toString().replace(/\$|\,/g,'');

	if(isNaN(num))
		num = "0";

	sign = (num == (num = Math.abs(num)));
	num = Math.floor(num * 100 + 0.50000000001);
	cents = num % 100;
	num = Math.floor(num / 100).toString();

	if(cents < 10)
		cents = "0" + cents;

	for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++)
		num = num.substring(0, num.length - (4 * i + 3)) + ',' + num.substring(num.length - (4 * i + 3));

	return (((sign) ? '' : '-') + '$' + num + '.' + cents);
}

function ncUI_IsNumeric (str)
{
	var i;

	for (i = 0; i < str.length; i++)
	{
		if (str.charCodeAt(i) < 48 || str.charCodeAt(i) > 57)
		{
			if (str.charCodeAt(i) != 46 && str.charCodeAt(i) != 32 && str.charAt(i) != ',')
				return false;
		}																					
	}

	return true;
}

function ncUI_Left (str, cnt)
{
	return str.substring(0, cnt);
}

function ncUI_Mid (str, start, end)
{
	if (!start)
		start = 0;

	if (!end || end > str.length)
		end = str.length;

	if (end != str.length)
		end = start + end;

	return str.substring(start, end);
}

function ncUI_Right (str, cnt)
{
	return str.substring(str.length - cnt, str.length);
}

function ncUI_Trim (str)
{
	return ncUI_RTrim(ncUI_LTrim(str));
}

function ncUI_RTrim (str)
{
	while (str.charAt(str.length - 1) == " ")
	{
		str = str.substring(0, str.length - 1);
	}

	return str;
}

function ncUI_LTrim (str)
{
	while (str.charAt(0) == " ")
	{
		str = str.replace(str.charAt(0), "");
	}

	return str;
}

function ncUI_IsCurrency(strValue)
{
	strValue = ncUI_Trim(strValue);

	if (ncUI_Left(strValue, 1) == "$")
		strValue = ncUI_Mid (strValue, 1, strValue.length);

	return ncUI_IsNumeric(strValue);
}

function ncUI_RemoveSpaces(string)
{
	var tstring = "";

	string = '' + string;
	splitstring = string.split(" ");

	for(i = 0; i < splitstring.length; i++)
		tstring += splitstring[i];

	if (splitstring.length == 0)
		return "";
	else
		return tstring;
}

/* Given a date or month, finds the last day of that month. */
function ncUI_MonthEnd(dDate)
{
	var dTemp;

    /* If this month is december, we need to do something special..
    *  add 1 to year, then set month to 1. Else, just increment month. */
    if (dDate.getMonth() == 11)		/* JS = funny. Months are 0..11 */
        dTemp = new Date(1900 + dDate.getYear() + 1, 0, 1);
    else
        dTemp = new Date(1900 + dDate.getYear(), dDate.getMonth() + 1, 1);

    /* Subtract 1 day from our temporary date, this is the end of the month for dDate. */
    dTemp.setTime(dTemp.getTime() - (24 * 3600 * 1000));	/* 24 hours */

    return dTemp;
}

/* Given a PermitLengthObject which is flagged as Month, find out the
*  closest expiry time that does not go over PL.Days */
function ncUI_MonthExpFit (objPL, dRelative)
{
    /* Calculate the end date of this PermitLength. */
    var dCompare = new Date();
    dCompare.setTime(dRelative.getTime() + (objPL.Days * 24 * 3600 * 1000));

    /* Calculate the same date, but exactly one month before. */
    if (dCompare.getMonth() == 0)		/* JS = funny. Months are 0..11 */
		dCompare = new Date(1900 + dCompare.getYear() - 1, 11, dCompare.getDate());
    else
		dCompare = new Date(1900 + dCompare.getYear(), dCompare.getMonth() - 1, dCompare.getDate());

	/* Calculate the end of the month to come up with the expiry date. */
	return ncUI_MonthEnd(dCompare);
}

/* Given a PermitLengthObject which is flagged as Term and an array of
*  available term expiry dates, find out the closest expiry date without
*  going over PL.Days */
function ncUI_TermExpFit (objPL, dRelative, aDates)
{
    var dCompare = new Date();
    var dClosest = new Date();
    var i;

    /* Set the date to compare with */
    dCompare.setTime(dRelative.getTime() + (objPL.Days * 24 * 3600 * 1000));

    /* If there are no expiry dates defined, then we should just go
    *  relative to the start date by objPL.Days */
    if (aDates.length == 0)
		return dCompare;

    /* Set first entry to the lowest date for now */
    dClosest.setTime(aDates[0].getTime());
    for (i = 0; i < aDates.length; i++)
    {
		/* If current check is less than current lowest, reset current lowest. */
		if (aDates[i].getTime() < dClosest.getTime())
			dClosest.setTime(aDates[i].getTime());
	}

	/* Go through each of the dates to find the closest one without going over. */
    for (i = 0; i < aDates.length; i++)
	{
		/* If the maximum allowed date is greater than the date we want to check... */
		if (dCompare >= aDates[i])
		{
			/* ...and the date we want to check is greater than the current closest value... */
			if (aDates[i] >= dClosest)
			{
				/* Then reset the new closest date. */
				dClosest.setTime(aDates[i].getTime());
			}
		}
	}

    /* Here's the closest fitting date! */
    return dClosest;
}

function ncUI_GetExpiryCalculated (dStartDate, oPL, oOutput, aDates, dYearEnd)
{
	oOutput.PermitLengthID = oPL.ID;

	if (oPL.IsExpYear == true)
	{
		oOutput.ExpDate = dYearEnd;
//		oOutput.ModifiedDays = DateDiff("d", dStartDate, oOutput.ExpDate);
		oOutput.ModifiedPrice = oPL.Price;
	}
	else if (oPL.IsExpTerm == true)
	{
		oOutput.ExpDate = ncUI_TermExpFit(oPL, dStartDate, aDates);
//		oOutput.ModifiedDays = DateDiff("d", dStartDate, oOutput.ExpDate)
		oOutput.ModifiedPrice = oPL.Price;
	}
	else if (oPL.IsExpMonth == true)
	{
		oOutput.ExpDate = ncUI_MonthExpFit(oPL, dStartDate);
//      oOutput.ModifiedDays = DateDiff("d", dStartDate, oOutput.ExpDate)
		oOutput.ModifiedPrice = ncUI_MonthCalculatePricing(dStartDate, oPL.Price, doGetMaxPLPrice(7, oPL.AllowStaff, oPL.AllowStudent, 14 * ncUI_TaxFactorInvert()), doGetMaxPLPrice(1, oPL.AllowStaff, oPL.AllowStudent, 4 * ncUI_TaxFactorInvert()));
	}
	else
	{
		oOutput.ExpDate = new Date();
		oOutput.ExpDate.setTime(dStartDate.getTime() + (oPL.Days * 24 * 3600 * 1000));
        oOutput.ModifiedDays = oPL.Days;
		oOutput.ModifiedPrice = oPL.Price;
	}
}

function ncUI_TermCalculatePricing(dStartDate, dExpDate, cBase, cMonthPrice)
{
	var iTotalMonths;

//	iTotalMonths = 
}

function ncUI_MonthCalculatePricing (dDate, cBase, cWeekPrice, cDayPrice)
{
	var dMonthEnding;
	var iTotalDays;
	var iCurrentDay;

	/* Find the number of days in this month */
	iTotalDays = ncUI_MonthEnd(dDate).getDate();

	cBase = cBase * ncUI_TaxFactor();
	cWeekPrice = cWeekPrice * ncUI_TaxFactor();
	cDayPrice = cDayPrice * ncUI_TaxFactor();

	if (dDate.getDate() < 14)
		return cBase * ncUI_TaxFactorInvert();
    else if ((iTotalDays - dDate.getDate()) < 5)
    {
		var x = dDate.getDate() - iTotalDays + 4;
		return Math.floor((-cWeekPrice * 0.05 * x * x) + (cDayPrice * 0.1 * x) + cWeekPrice) * ncUI_TaxFactorInvert();
	}
	else
		return Math.ceil((((cBase - cWeekPrice) / (0 - (iTotalDays - 14 - 4))) * (dDate.getDate() - 14)) + cBase) * ncUI_TaxFactorInvert();
}

function doGetPermitLength (id_value)
{
	var i;
	for (i = 0; i < NCPermitLengths.length; i++)
	{
		if (NCPermitLengths[i]["ID"] == id_value)
			return NCPermitLengths[i];
	}
	return 0;
}

function doGetPaymentMethodIsDeduction (id_value)
{
	var i;
	for (i = 0; i < NCPaymentMethods.length; i++)
	{
		if (NCPaymentMethods[i]["ID"] == id_value)
			return NCPaymentMethods[i]["PayrollDeduction"];
	}
	return false;
}

function doGetPaymentMethodIsBackcharge (id_value)
{
	var i;
	for (i = 0; i < NCPaymentMethods.length; i++)
	{
		if (NCPaymentMethods[i]["ID"] == id_value)
			return NCPaymentMethods[i]["BackCharge"];
	}
	return false;
}

function doGetMaxPLPrice(iDays, bStaff, bStudents, cBasePrice)
{
	var i;
	var cPrice = 0;

	for (i = 0; i < NCPermitLengths.length; i++)
	{
		if (NCPermitLengths[i].Days == iDays && NCPermitLengths[i].AllowStaff == bStaff && NCPermitLengths[i].AllowStudent == bStudents)
		{
			if (NCPermitLengths[i].Price > cPrice)
				cPrice = NCPermitLengths[i].Price;
		}
	}

	if (cPrice == 0) cPrice = cBasePrice;

	return cPrice;
}

// -----------------------------------------------------
// Get window width in pixels; returns 0 if unidentifiable.
// -----------------------------------------------------
function getWindowWidth()
{
	var ww = 0;
	d = document;
	if ( typeof window.innerWidth != 'undefined' )
		ww = window.innerWidth;  // NN and Opera version
	else
	{
		if ( d.documentElement && typeof d.documentElement.clientWidth!='undefined' && d.documentElement.clientWidth != 0 )
			ww = d.documentElement.clientWidth;
		else if ( d.body && typeof d.body.clientWidth != 'undefined' )
			ww = d.body.clientWidth;
		else alert ("Can't identify window width - please tell me which browser you are using.")
	}
	return ww;
}
				
// -----------------------------------------------------
// Get window height in pixels; returns 0 if unidentifiable.
// -----------------------------------------------------
function getWindowHeight()
{
	var wh = 0;
	d = document;
	if ( typeof window.innerHeight != 'undefined' )
		wh = window.innerHeight;  // NN and Opera version
	else
	{
		if ( d.documentElement && typeof d.documentElement.clientHeight!='undefined' && d.documentElement.clientHeight != 0 )
			wh = d.documentElement.clientHeight;
		else if ( d.body && typeof d.body.clientHeight != 'undefined' )
			wh = d.body.clientHeight;
		else alert ("Can't identify window height - please tell me which browser you are using.")
	}
	return wh;
}

// -----------------------------------------------------
// Get scroll offset in X pixels; returns 0 if unidentifiable.
// -----------------------------------------------------
function getScrollOffsetX()
{
	var wx = 0;
	if ( typeof window.pageXOffset != 'undefined' )
		wx = window.pageXOffset;  // NN and Opera version
	else
		wx = document.body.scrollLeft;
	return wx;
}

// -----------------------------------------------------
// Get scroll offset in Y pixels; returns 0 if unidentifiable.
// -----------------------------------------------------
function getScrollOffsetY()
{
	var wy = 0;	/* because I said so. */
	if ( typeof window.pageYOffset != 'undefined' )
		wy = window.pageYOffset;  // NN and Opera version
	else
		wy = document.body.scrollTop;
	return wy;
}
