/**
* Calculation Help Functions
* -------------------------------------
* @desc		script contains helper methods for calculating, validating and pre-populating fields
*
* $Id: calculation.js,v 1.2 2005/04/09 13:05:45 demid Exp $
*/

// BEGIN: Constants definition in weeks number
top.TOTAL_WEEKS		= 52;

top.errorMessages = new Array(
	new Array("billable_hours_target", "You must enter a positive number for the Billable Hours Target"),
	new Array("vacation_days", "You must enter a positive number for the vacation field"),
	new Array("personal_days", "You must enter a positive number for the personal field"),
	new Array("legal_holidays", "You must enter a positive number for the legal holidays field"),
	new Array("vacation_days_exceed", "Holidays, Vacation and Personal days can not exceed 52 weeks"),
	new Array("office_time_equals", "You have selected the same Arrive Office and Office Leave for %DAY%"),
	new Array("break_time_exceed", "The number of hours selected for nonbillable activities exceeds the number of hours in the office for %DAY%")
)

// END: Constants definition
top.errors = new Array();


/**
* Initialization method. Evaluates when document is loaded (onload event)
* call pre-populating methods to complete loading
*/
function init(){
	// BEGIN: preparing structure
	// populates select boxes for Arrive Office
	populate_time(document.getElementById('arrive_office_1'), '4:00 AM', '1:00 PM', 30);
	populate_time(document.getElementById('arrive_office_2'), '4:00 AM', '1:00 PM', 30);
	populate_time(document.getElementById('arrive_office_3'), '4:00 AM', '1:00 PM', 30);
	populate_time(document.getElementById('arrive_office_4'), '4:00 AM', '1:00 PM', 30);
	populate_time(document.getElementById('arrive_office_5'), '4:00 AM', '1:00 PM', 30);

	// populates select boxes for Leave Office
	populate_time(document.getElementById('leave_office_1'), '1:30 PM', '3:30 AM', 30);
	populate_time(document.getElementById('leave_office_2'), '1:30 PM', '3:30 AM', 30);
	populate_time(document.getElementById('leave_office_3'), '1:30 PM', '3:30 AM', 30);
	populate_time(document.getElementById('leave_office_4'), '1:30 PM', '3:30 AM', 30);
	populate_time(document.getElementById('leave_office_5'), '1:30 PM', '3:30 AM', 30);

	// populates break time for lunch breaks
	populate_break_time(document.getElementById('lunch_break_1'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('lunch_break_2'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('lunch_break_3'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('lunch_break_4'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('lunch_break_5'), false, false, 10, 15, 1);

	// populates break time for lunch breaks
	populate_break_time(document.getElementById('personal_break_1'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('personal_break_2'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('personal_break_3'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('personal_break_4'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('personal_break_5'), false, false, 10, 15, 1);

	// populates break time for lunch breaks
	populate_break_time(document.getElementById('professional_break_1'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('professional_break_2'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('professional_break_3'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('professional_break_4'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('professional_break_5'), false, false, 10, 15, 1);
	// populates break time for lunch breaks
	populate_break_time(document.getElementById('administrative_break_1'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('administrative_break_2'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('administrative_break_3'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('administrative_break_4'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('administrative_break_5'), false, false, 10, 15, 1);

	// populates break time for lunch breaks
	populate_break_time(document.getElementById('dinner_break_1'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('dinner_break_2'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('dinner_break_3'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('dinner_break_4'), false, false, 10, 15, 1);
	populate_break_time(document.getElementById('dinner_break_5'), false, false, 10, 15, 1);

	// populates commuting time
	populate_break_time(document.getElementById('morning_commuting_time_1'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('morning_commuting_time_2'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('morning_commuting_time_3'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('morning_commuting_time_4'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('morning_commuting_time_5'), false, false, 10, 15, false);
	// populates commuting time
	populate_break_time(document.getElementById('evening_commuting_time_1'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('evening_commuting_time_2'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('evening_commuting_time_3'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('evening_commuting_time_4'), false, false, 10, 15, false);
	populate_break_time(document.getElementById('evening_commuting_time_5'), false, false, 10, 15, false);

	// END: preparing structure

	// BEGIN: populate calculable fields
	populate_office_hours();
	populate_get_home();
	populate_leave_home();
	populate_working_weeks();
	populate_nonbillable_time();
	populate_billable_time();
	// END: populate calculable fields
}

function popUp(URL) {
var windowName = 'NewWin';
var features = 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=400,height=400';
var newWindow = window.open (URL, windowName, features);
newWindow.focus();
}

/**
* Populates select box with time values, ie 10:30 AM, 11:00 AM etc
* @param	HTMLSelectElement	ctrl
* @return	bool
*/
function populate_time(ctrl, beginTime, endTime, interval){
	if(!ctrl){
		return false;
	}

	// interval in minutes between time records
	if(!interval){
		interval = 30;
	}

	if(!beginTime){
		beginTime = '12:00 AM';
	}

	if(!endTime){
		endTime = '12:00 AM';
	}

	var tokens = endTime.substr(0, endTime.indexOf(' ')).split(":");
	var pm_am = endTime.substr(endTime.indexOf(' ') + 1).toUpperCase();
	var endHour = 
		tokens[0] == '12' &&  pm_am == 'AM' ? 24 : 
		tokens[0] == '12' &&  pm_am == 'PM' ? 12 :
		pm_am == 'PM' ? 12 + tokens[0] * 1 : tokens[0] * 1;

	var endMinutes = tokens[1] * 1;

	tokens = beginTime.substr(0, beginTime.indexOf(' ')).split(":");
	pm_am = beginTime.substr(beginTime.indexOf(' ') + 1).toUpperCase();
	
	// sets current hour
	curHour = 
		tokens[0] == '12' &&  pm_am == 'AM' ? 0 : 
		tokens[0] == '12' &&  pm_am == 'PM' ? 12 : 
		pm_am == 'PM' ? 12 + tokens[0] * 1 : tokens[0] * 1;

	curMinutes = tokens[1] * 1;

	if((curHour * 60 + curMinutes) > (endHour * 60 + endMinutes)){
		endHour += 24;
	}

	var iter = Math.floor(((endHour * 60 + endMinutes) - (curHour * 60 + curMinutes)) / interval) + 1;

	var changePmAm = true;
	// add options for each time element
	for(var i = 0; i < iter; i++){
		// creates option DOMElement and fill it with value
		var optionNode = document.createElement('option');

		// prepare value for time
		var __hour = curHour == 0 ? 12 : curHour > 12 ? curHour - 12 : curHour;
		var value = __hour.toString().__addChar(2, '0');
		value += ':' + curMinutes.toString().__addChar(2, '0') + ' ' + pm_am;

		optionNode.innerHTML = value;
		// prepare value attribute
		var truevalue = '';
		if(pm_am == 'PM' && __hour != 12){
			truevalue = (__hour + 12) * 60 + curMinutes;

		}else if(pm_am == 'AM' && __hour == 12){
			truevalue = curMinutes;

		}else{
			truevalue = __hour * 60 + curMinutes;
		}

		optionNode.setAttribute('value', truevalue);

		// append option element
		ctrl.appendChild(optionNode);

		// increase time by interval
		curMinutes += interval;
		if(curMinutes >= 60){
			curHour += Math.floor(curMinutes / 60);
			curMinutes = curMinutes % 60;
		}

		// tries to set 'PM' if need
		if(
			curHour >= 12 && 
			Math.floor((curHour * 60 + curMinutes - interval) / 60) < 12 && 
			changePmAm
		){
			pm_am = pm_am == 'PM' ? 'AM' : 'PM';
			changePmAm = false;
		}

		if(curHour >= 24){
			curHour = 0;
			pm_am = pm_am == 'PM' ? 'AM' : 'PM';
		}
	}
	return true;
}

/**
* Populates select box with time values, ie 10:30 AM, 11:00 AM etc
* @param	HTMLSelectElement	ctrl
* @param	int					beginHour
* @param	int		            beginMinute
* @param	int					iterations
* @param	int					interval
* @return	bool
*/
function populate_break_time(ctrl, beginHour, beginMinute, iterations, interval, addzero){
	if(!ctrl){
		return false;
	}

	// interval in minutes between time records
	if(!interval){
		var interval = 15;
	}

	var curHour = beginHour ? beginHour : 0;
	var curMinutes = beginMinute ? beginMinute : 15;

	if(!iterations){
		iterations = Math.floor((5 * 60) / interval);
	}
	
	// constant suffixes for hours and minutes (for viwe)
	var SUFFIX_HOUR		= ' hr ';
	var SUFFIX_MINUTE	= ' min ';

	if(addzero){
	// add first field
	var node = document.createElement('option');
	node.setAttribute('value', 0);
	node.innerHTML = '0 min';
	// append option element
	ctrl.appendChild(node);
	}

	
	// add options for each time element
	for(var i = 0; i < iterations; i++){
		// creates option DOMElement and fill it with value
		var optionNode = document.createElement('option');

		var truevalue = curHour * 60 + curMinutes; 
		// sets value attribute
		optionNode.setAttribute('value', truevalue);

		// prepare value for time
		var value = curHour == 0 ? '' : curHour + SUFFIX_HOUR;
		value += curMinutes == 0 ? '' : curMinutes + SUFFIX_MINUTE;

		optionNode.innerHTML = value;

		// append option element
		ctrl.appendChild(optionNode);

		// increase time by interval
		curMinutes += interval;
		if(curMinutes >= 60){
			curHour += Math.floor(curMinutes / 60);
			curMinutes = curMinutes % 60;
		}
	}

	return true;
}

/**
* Handler for changing arrive office time for Monday
* @param	HTMLElement		ctrl
*/
function changeArriveOffice(ctrl){
	if(!ctrl){
		return false;
	}

	var value = ctrl.value;
	populate_office_hours();
	populate_leave_home();

	populate_billable_time();
	var id = ctrl.id;
	var __ctrl = __getCtrl('lunch_break_' + id.toString().substr(id.length - 1, 1));
	
	if(!validate_break_time(__ctrl, id.toString().substr(id.length - 1, 1))){
		return false;
	}


	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('arrive_office_2', value);
		changeArriveOffice(document.getElementById('arrive_office_2'));

		__setSelectBoxIndexByValue('arrive_office_3', value);
		changeArriveOffice(document.getElementById('arrive_office_3'));

		__setSelectBoxIndexByValue('arrive_office_4', value);
		changeArriveOffice(document.getElementById('arrive_office_4'));

		__setSelectBoxIndexByValue('arrive_office_5', value);
		changeArriveOffice(document.getElementById('arrive_office_5'));
	}
}

/**
* Handler for changing vacation days
* @param	HTMLElement		ctrl
*/
function changeVacationDays(ctrl){
	if(!ctrl){
		return false;
	}

	populate_working_weeks();

	if(!validate_vacation_days(ctrl)){
		return false;
	}
}

/**
* Handler for changing personal  days
* @param	HTMLElement		ctrl
*/
function changePersonalDays(ctrl){
	if(!ctrl){
		return false;
	}

	populate_working_weeks();

	if(!validate_personal_days(ctrl)){
		return false;
	}
}

/**
* Handler for changing legal holidays
* @param	HTMLElement		ctrl
*/
function changeLegalHolidays(ctrl){
	if(!ctrl){
		return false;
	}

	populate_working_weeks();

	if(!validate_legal_holidays(ctrl)){
		return false;
	}
}

/**
* Handler for changing leave office time for Monday
* @param	HTMLElement		ctrl
*/
function changeLeaveOffice(ctrl){
	if(!ctrl){
		return false;
	}

	var value = ctrl.value;
	populate_office_hours();
	populate_get_home();

	populate_billable_time();
	var id = ctrl.id;
	var __ctrl = __getCtrl('lunch_break_' + id.toString().substr(id.length - 1, 1));
	
	if(!validate_break_time(__ctrl, id.toString().substr(id.length - 1, 1))){
		return false;
	}
	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('leave_office_2', value);
		changeLeaveOffice(document.getElementById('leave_office_2'));

		__setSelectBoxIndexByValue('leave_office_3', value);
		changeLeaveOffice(document.getElementById('leave_office_3'));

		__setSelectBoxIndexByValue('leave_office_4', value);
		changeLeaveOffice(document.getElementById('leave_office_4'));

		__setSelectBoxIndexByValue('leave_office_5', value);
		changeLeaveOffice(document.getElementById('leave_office_5'));
	}
}

/**
* Handler for changing evening commute for Monday
* @param	HTMLElement		ctrl
*/
function changeEveningCommute(ctrl){
	if(!ctrl){
		return false;
	}

	var value = ctrl.value;
	populate_get_home();

	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('evening_commuting_time_2', value);
		changeEveningCommute(__getCtrl('evening_commuting_time_2'));

		__setSelectBoxIndexByValue('evening_commuting_time_3', value);
		changeEveningCommute(__getCtrl('evening_commuting_time_3'));

		__setSelectBoxIndexByValue('evening_commuting_time_4', value);
		changeEveningCommute(__getCtrl('evening_commuting_time_4'));

		__setSelectBoxIndexByValue('evening_commuting_time_5', value);
		changeEveningCommute(__getCtrl('evening_commuting_time_5'));
	}
}

/**
* Handler for changing morning commute for Monday
* @param	HTMLElement		ctrl
* @return	bool
*/
function changeMorningCommute(ctrl){
	if(!ctrl){
		return false;
	}

	var value = ctrl.value;
	populate_leave_home();

	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('morning_commuting_time_2', value);
		changeMorningCommute(__getCtrl('morning_commuting_time_2'));

		__setSelectBoxIndexByValue('morning_commuting_time_3', value);
		changeMorningCommute(__getCtrl('morning_commuting_time_3'));

		__setSelectBoxIndexByValue('morning_commuting_time_4', value);
		changeMorningCommute(__getCtrl('morning_commuting_time_4'));

		__setSelectBoxIndexByValue('morning_commuting_time_5', value);
		changeMorningCommute(__getCtrl('morning_commuting_time_5'));
	}
}

/**
* Handler for changing lunch break for Monday
* @param	HTMLElement		ctrl
* @return	bool
*/
function changeLunchBreak(ctrl){
	if(!ctrl){
		return false;
	}

	populate_nonbillable_time();
	populate_billable_time();

	var id = ctrl.id;
	if(!validate_break_time(ctrl, id.toString().substr(id.length - 1, 1))){
		return false;
	}

	var value = ctrl.value;

	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('lunch_break_2', value);
		changeLunchBreak(__getCtrl('lunch_break_2'));

		__setSelectBoxIndexByValue('lunch_break_3', value);
		changeLunchBreak(__getCtrl('lunch_break_3'));

		__setSelectBoxIndexByValue('lunch_break_4', value);
		changeLunchBreak(__getCtrl('lunch_break_4'));

		__setSelectBoxIndexByValue('lunch_break_5', value);
		changeLunchBreak(__getCtrl('lunch_break_5'));
	}
}


/**
* Handler for changing personal break for Monday
* @param	HTMLElement		ctrl
* @return	bool
*/
function changePersonalBreak(ctrl){
	if(!ctrl){
		return false;
	}

	populate_nonbillable_time();
	populate_billable_time();

	var id = ctrl.id;
	if(!validate_break_time(ctrl, id.toString().substr(id.length - 1, 1))){
		return false;
	}

	var value = ctrl.value;

	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('personal_break_2', value);
		changePersonalBreak(__getCtrl('personal_break_2'));

		__setSelectBoxIndexByValue('personal_break_3', value);
		changePersonalBreak(__getCtrl('personal_break_3'));

		__setSelectBoxIndexByValue('personal_break_4', value);
		changePersonalBreak(__getCtrl('personal_break_4'));

		__setSelectBoxIndexByValue('personal_break_5', value);
		changePersonalBreak(__getCtrl('personal_break_5'));
	}
}

/**
* Handler for changing professional break for Monday
* @param	HTMLElement		ctrl
* @return	bool
*/
function changeProfessionalBreak(ctrl){
	if(!ctrl){
		return false;
	}

	populate_nonbillable_time();
	populate_billable_time();

	var id = ctrl.id;
	if(!validate_break_time(ctrl, id.toString().substr(id.length - 1, 1))){
		return false;
	}

	var value = ctrl.value;

	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('professional_break_2', value);
		changeProfessionalBreak(__getCtrl('professional_break_2'));

		__setSelectBoxIndexByValue('professional_break_3', value);
		changeProfessionalBreak(__getCtrl('professional_break_3'));

		__setSelectBoxIndexByValue('professional_break_4', value);
		changeProfessionalBreak(__getCtrl('professional_break_4'));

		__setSelectBoxIndexByValue('professional_break_5', value);
		changeProfessionalBreak(__getCtrl('professional_break_5'));
	}
}

/**
* Handler for changing administrative break for Monday
* @param	HTMLElement		ctrl
* @return	bool
*/
function changeAdministrativeBreak(ctrl){
	if(!ctrl){
		return false;
	}

	populate_nonbillable_time();
	populate_billable_time();

	var id = ctrl.id;
	if(!validate_break_time(ctrl, id.toString().substr(id.length - 1, 1))){
		return false;
	}

	var value = ctrl.value;

	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('administrative_break_2', value);
		changeAdministrativeBreak(__getCtrl('administrative_break_2'));

		__setSelectBoxIndexByValue('administrative_break_3', value);
		changeAdministrativeBreak(__getCtrl('administrative_break_3'));

		__setSelectBoxIndexByValue('administrative_break_4', value);
		changeAdministrativeBreak(__getCtrl('administrative_break_4'));

		__setSelectBoxIndexByValue('administrative_break_5', value);
		changeAdministrativeBreak(__getCtrl('administrative_break_5'));
	}
}

/**
* Handler for changing administrative break for Monday
* @param	HTMLElement		ctrl
* @return	bool
*/
function changeDinnerBreak(ctrl){
	if(!ctrl){
		return false;
	}

	populate_nonbillable_time();
	populate_billable_time();

	var id = ctrl.id;
	if(!validate_break_time(ctrl, id.toString().substr(id.length - 1, 1))){
		return false;
	}

	var value = ctrl.value;

	var isAffecting = ctrl.getAttribute('is_affecting');

	if(isAffecting){
		__setSelectBoxIndexByValue('dinner_break_2', value);
		changeDinnerBreak(__getCtrl('dinner_break_2'));

		__setSelectBoxIndexByValue('dinner_break_3', value);
		changeDinnerBreak(__getCtrl('dinner_break_3'));

		__setSelectBoxIndexByValue('dinner_break_4', value);
		changeDinnerBreak(__getCtrl('dinner_break_4'));

		__setSelectBoxIndexByValue('dinner_break_5', value);
		changeDinnerBreak(__getCtrl('dinner_break_5'));
	}
}

/**
* Tries to set select box index by its id
* @param	DOMString	id
* @param	int			index
* @return	bool
* @access	private
*/
function __setSelectBoxIndex(id, index){
	var ctrl = document.getElementById(id);	
	if(!ctrl){
		return false;
	}

	ctrl.selectedIndex = index;

	return true;
}

/**
* Tries to set select box index by its value
* @param	DOMString	id
* @param	String		index
* @return	bool
* @access	private
*/
function __setSelectBoxIndexByValue(id, value){
	var ctrl = document.getElementById(id);	
	if(!ctrl){
		return false;
	}

	var options = ctrl.options;
	for(var i = 0; i < options.length; i++){
		if(options.item(i).value == value){
			ctrl.selectedIndex = i;

			break;
		}
	}

	return true;
}


/**
* Calculate difference between 2 time values. Returns result in hours
* @param	int			minuend
* @param	int			subtrahend
* @return	int
*/
function __getTimeDifference(minuend, subtrahend){
	// if have a difference AM/PM increase mHour with 12 hours.
	if(1 * minuend < 1 * subtrahend){
		minuend = minuend * 1 + (24 * 60);
	}

	return (minuend - subtrahend) / 60;
}

/**
* Calculate summ of 2 time values. Returns result in hours
* @param	int			minuend
* @param	int			subtrahend
* @return	int
*/
function __getTimeSumm(){
	if(!__getTimeSumm.arguments){
		return 0;
	}

	var sum = 0;
	for(var i = 0; i < __getTimeSumm.arguments.length; i++){
		sum += __getTimeSumm.arguments[i] * 1;
	}


	return sum / 60;
}

/**
* Sets value attribute for specified control by name
* @param	DOMString	id
* @param	String		value
* @access	private
*/
function __setValue(id, value){
	var ctrl = document.getElementById(id);
	if(!ctrl){
		return false;
	}

	ctrl.value = value;
}

/**
* Gets value attribute for specified control by name
* @param	DOMString	id
* @return	String
* @access	private
*/
function __getValue(id){
	var ctrl = document.getElementById(id);
	if(!ctrl){
		return false;
	}

	return ctrl.value;
}

/**
* Gets control by id
* @param	DOMString	id
* @return	HTMLElement
* @access	private
*/
function __getCtrl(id){
	return document.getElementById(id);
}

/**
* Outputs formatted time like HH:MM AM(PM)
* @param	int		time
* @return	String
* @access	private
*/
function __formatTime(time){
	var __hour = Math.floor(time);
	var __minute = (time - Math.floor(time)) * 60;
	var pm_am = 'AM';
	
	// change pm_am if need
	if(__hour > 12){
		pm_am = 'PM';
		__hour -= 12;
	}

	if(__hour == 0){
		__hour = 12;
	}

	return 	__hour.toString().__addChar(2, '0') + ":" +	__minute.toString().__addChar(2, '0') + ' ' + pm_am;
}


/**
* Calculates result based on the input data. Raises error if any
*/
function calculate(){
    // check for errors
    if(!check_validating()){
    	return false;
    }
	// sets office hours
	populate_office_hours_per_week();

	populate_billable_hours_per_week();
	populate_office_hours_per_year();
	populate_billable_hours_per_year();
	populate_percentage_billable_time();
	populate_weekend_time_per_year();
	populate_weekend_time_per_week();

	// sets caption for buttons
	__getCtrl('btn_calculate_1').innerHTML = 'Re-Calculate';
	__getCtrl('btn_calculate_2').innerHTML = 'Re-Calculate';
}



/**
* Populates working weeks count
*/
function populate_working_weeks(){
	var value = 
		top.TOTAL_WEEKS - 
		__getValue('total_legal_holidays') / 7 - 
		__getValue('total_vacation_days') / 7 - 
		__getValue('total_personal_days') / 7

	if(
		isNaN(parseInt(value)) || 
		__getValue('total_legal_holidays') * 1 < 0 ||
		__getValue('total_vacation_days') * 1 < 0 ||
		__getValue('total_personal_days') * 1 < 0 || 
		parseInt(value) < 0
	){

		value = '';
    	__getCtrl('total_working_weeks').className = 'std_input_error';
	}else{
    	__getCtrl('total_working_weeks').className = 'std_input';
		value = new Number(value).toFixed(2);
	}

	__setValue(
		'total_working_weeks',
		value
	);
}

/**
* Populates non-billable hours based on selected data
*/
function populate_nonbillable_time(){
	__setValue(
		'total_nonbillable_1', 
		__getTimeSumm(
			__getValue('lunch_break_1'),
			__getValue('personal_break_1'),
			__getValue('professional_break_1'),
			__getValue('administrative_break_1'),
			__getValue('dinner_break_1')
		)
	);
	__setValue(
		'total_nonbillable_2', 
		__getTimeSumm(
			__getValue('lunch_break_2'),
			__getValue('personal_break_2'),
			__getValue('professional_break_2'),
			__getValue('administrative_break_2'),
			__getValue('dinner_break_2')
		)
	);
	__setValue(
		'total_nonbillable_3', 
		__getTimeSumm(
			__getValue('lunch_break_3'),
			__getValue('personal_break_3'),
			__getValue('professional_break_3'),
			__getValue('administrative_break_3'),
			__getValue('dinner_break_3')
		)
	);
	__setValue(
		'total_nonbillable_4', 
		__getTimeSumm(
			__getValue('lunch_break_4'),
			__getValue('personal_break_4'),
			__getValue('professional_break_4'),
			__getValue('administrative_break_4'),
			__getValue('dinner_break_4')
		)
	);
	__setValue(
		'total_nonbillable_5', 
		__getTimeSumm(
			__getValue('lunch_break_5'),
			__getValue('personal_break_5'),
			__getValue('professional_break_5'),
			__getValue('administrative_break_5'),
			__getValue('dinner_break_5')
		)
	);
}

/**
* Populates billable hours based on selected data
*/
function populate_billable_time(){
	// billable time
	var value = 0;

	value =
		__getValue('total_hours_in_office_1') -
		__getValue('total_nonbillable_1');
	
    if(value < 0){
    	value = '';
    	__getCtrl('total_billable_1').className = 'std_input_error';
    }else{
    	__getCtrl('total_billable_1').className = 'std_input';
    }

	__setValue(
		'total_billable_1', 
		value 
	);

	value =
		__getValue('total_hours_in_office_2') -
		__getValue('total_nonbillable_2');

    if(value < 0){
    	value = '';
    	__getCtrl('total_billable_2').className = 'std_input_error';
    }else{
    	__getCtrl('total_billable_2').className = 'std_input';
    }

	__setValue(
		'total_billable_2', 
		value 
	);

	value =
		__getValue('total_hours_in_office_3') -
		__getValue('total_nonbillable_3');

    if(value < 0){
    	value = '';
    	__getCtrl('total_billable_3').className = 'std_input_error';
    }else{
    	__getCtrl('total_billable_3').className = 'std_input';
    }


	__setValue(
		'total_billable_3', 
		value 
	);

	value =
		__getValue('total_hours_in_office_4') -
		__getValue('total_nonbillable_4');

    if(value < 0){
    	value = '';
    	__getCtrl('total_billable_4').className = 'std_input_error';
    }else{
    	__getCtrl('total_billable_4').className = 'std_input';
    }

	__setValue(
		'total_billable_4', 
		value 
	);

	value =
		__getValue('total_hours_in_office_5') -
		__getValue('total_nonbillable_5');

    if(value < 0){
    	value = '';
    	__getCtrl('total_billable_5').className = 'std_input_error';
    }else{
    	__getCtrl('total_billable_5').className = 'std_input';
    }

	__setValue(
		'total_billable_5',
		value 
	);
}


/**
* Populates office hours fields based on selected data
*/
function populate_office_hours(){
	// sets total office hour
	__setValue(
		'total_hours_in_office_1', 
		__getTimeDifference(
			__getValue('leave_office_1'),
			__getValue('arrive_office_1')
		)
	);	
	__setValue(
		'total_hours_in_office_2', 
		__getTimeDifference(
			__getValue('leave_office_2'),
			__getValue('arrive_office_2')
		)
	);	
	__setValue(
		'total_hours_in_office_3', 
		__getTimeDifference(
			__getValue('leave_office_3'),
			__getValue('arrive_office_3')
		)
	);	
	__setValue(
		'total_hours_in_office_4', 
		__getTimeDifference(
			__getValue('leave_office_4'),
			__getValue('arrive_office_4')
		)
	);	
	__setValue(
		'total_hours_in_office_5', 
		__getTimeDifference(
			__getValue('leave_office_5'),
			__getValue('arrive_office_5')
		)
	);	
}

/**
* Sets office hours per week field
*/
function populate_office_hours_per_week(){
	__setValue(
		'office_hours_per_week',
		__getValue('total_hours_in_office_1') * 1 + 
		__getValue('total_hours_in_office_2') * 1 + 
		__getValue('total_hours_in_office_3') * 1 + 
		__getValue('total_hours_in_office_4') * 1 + 
		__getValue('total_hours_in_office_5') * 1
	);
}

/**
* Sets billable hours per week field
*/
function populate_billable_hours_per_week(){
	__setValue(
		'billable_hours_per_week',
		__getValue('total_billable_1') * 1 + 
		__getValue('total_billable_2') * 1 + 
		__getValue('total_billable_3') * 1 + 
		__getValue('total_billable_4') * 1 + 
		__getValue('total_billable_5') * 1
	);
}

/**
* Sets office hours per year field
*/
function populate_office_hours_per_year(){
	__setValue(
		'office_hours_per_year',
		new Number(__getValue('office_hours_per_week') * __getValue('total_working_weeks')).toFixed(2)
	);
}

/**
* Sets billable hours per year field
*/
function populate_billable_hours_per_year(){
	__setValue(
		'billable_hours_per_year',
		new Number(__getValue('billable_hours_per_week') * __getValue('total_working_weeks')).toFixed(2) 
	);
}

/**
* Sets billable hours per year field
*/
function populate_percentage_billable_time(){
	__setValue(
		'percentage_billable_time',
		new Number(
			__getValue('billable_hours_per_year') / __getValue('office_hours_per_year') * 100
		).toFixed(2) + '%'

	);
}


/**
* Sets weekends time per year field
*/
function populate_weekend_time_per_year(){
	var value = 
		(__getValue('billable_hours_target') * 1 - __getValue('billable_hours_per_year') * 1);
	// checks if billable_hours_target < billable_hours_per_year sets value to 0
	if(value < 0){
		value = 0;
	}

	__setValue(
		'weekend_time_per_year',
		new Number(value).toFixed(2)
	);
}
/**
* Sets billable hours per year field
*/
function populate_weekend_time_per_week(){
	var value = 
		(__getValue('billable_hours_target') * 1 - __getValue('billable_hours_per_year') * 1) / top.TOTAL_WEEKS;

	// checks if billable_hours_target < billable_hours_per_year sets value to 0
	if(value < 0){
		value = 0;
	}

	__setValue(
		'weekend_time_per_week',
		new Number(value).toFixed(2)
	);
}


/**
* Sets leave home time
*/
function populate_leave_home(){
	__setValue(
		'leave_home_1',
		__formatTime(
			__getTimeDifference(
				__getValue('arrive_office_1'),
				__getValue('morning_commuting_time_1')
			)
		)
	);

	__setValue(
		'leave_home_2',
		__formatTime(
			__getTimeDifference(
				__getValue('arrive_office_2'),
				__getValue('morning_commuting_time_2')
			)
		)
	);

	__setValue(
		'leave_home_3',
		__formatTime(
			__getTimeDifference(
				__getValue('arrive_office_3'),
				__getValue('morning_commuting_time_3')
			)
		)
	);
	__setValue(
		'leave_home_4',
		__formatTime(
			__getTimeDifference(
				__getValue('arrive_office_4'),
				__getValue('morning_commuting_time_4')
			)
		)
	);
	__setValue(
		'leave_home_5',
		__formatTime(
			__getTimeDifference(
				__getValue('arrive_office_5'),
				__getValue('morning_commuting_time_5')
			)
		)
	);
}

/**
* Sets get home time
*/
function populate_get_home(){
	__setValue(
		'get_home_1',
		__formatTime(
			__getTimeSumm(
				__getValue('leave_office_1'),
				__getValue('evening_commuting_time_1')
			)
		)
	);
	__setValue(
		'get_home_2',
		__formatTime(
			__getTimeSumm(
				__getValue('leave_office_2'),
				__getValue('evening_commuting_time_2')
			)
		)
	);
	__setValue(
		'get_home_3',
		__formatTime(
			__getTimeSumm(
				__getValue('leave_office_3'),
				__getValue('evening_commuting_time_3')
			)
		)
	);
	__setValue(
		'get_home_4',
		__formatTime(
			__getTimeSumm(
				__getValue('leave_office_4'),
				__getValue('evening_commuting_time_4')
			)
		)
	);
	__setValue(
		'get_home_5',
		__formatTime(
			__getTimeSumm(
				__getValue('leave_office_5'),
				__getValue('evening_commuting_time_5')
			)
		)
	);
}



// BEGIN: Validation functions here


/**
* gets label for specified control
* @param	HTMLElement		ctrl
*/
function __getLabel(ctrl){
	if(!ctrl){
		return '';
	}

	var id = ctrl.getAttribute('lbl');
	if(!id){
		return false;
	}

	return document.getElementById(id);
}

/**
* sets state for errors. sets style for label and pervent from calculation hitting
* @param	HTMLElement		ctrl
*/
function __setErrorState(id, msg, ctrl){
	__setErrorByCtrlId(id, msg);

	var lbl = __getLabel(ctrl);
	if(!lbl){
		return false;
	}

	lbl.className = 'std_text_error';
}

/**
* Return error by control id if exists
* @param	DOMString		id
*/
function __getErrorByCtrlId(id){
	for(var i = 0; i < top.errors.length; i++){
		if(top.errors[i][0] == id){
			return top.errors[i];
		}
	}

	return false;
}

/**
* Sets error by control id
* @param	DOMString		id
* @param	String			msg
*/
function __setErrorByCtrlId(id, msg){
	if(!__getErrorByCtrlId(id)){
		top.errors[top.errors.length] = new Array(id, msg);
	}
}


/**
* Removes error by control id
* @param	DOMString		id
*/
function __removeErrorByCtrlId(id){
	for(var i = 0; i < top.errors.length; i++){
		if(top.errors[i][0] == id){
			top.errors = top.errors.__remove(i);
		}
	}
}

/**
* sets normal state (without any errors) for application. 
* @param	HTMLElement		ctrl
*/
function __setNormalState(id, ctrl){
	__removeErrorByCtrlId(id);

	var lbl = __getLabel(ctrl);
	if(!lbl){
		return true;
	}

	lbl.className = 'std_text_bold';
}

/**
* gets caption for specified field
* @param	HTMLElement		ctrl
*/
function __getCaption(ctrl){
	var lbl = __getLabel(ctrl);
	if(!lbl)
		return '';

	return lbl.innerHTML;
}

/**
* validate control if it is int
* @param	HTMLElement		ctrl
* @param	String 			errId
*/
function validate_int(ctrl, errId){
	var value = ctrl.value;

	if(!isNaN(parseInt(value)) && parseInt(value) >= 0 && parseInt(value).toString().length == value.length){
		__setNormalState(ctrl.id, ctrl);
		return true;
	}

	var msg = __findErrorMessage(errId);
	__setErrorState(ctrl.id, msg, ctrl);
	riseError(msg);

	return false;
}

/**
* validate billable hours target field
* @param	HTMLElement	ctrl
*/
function validate_billable_hours_target(ctrl){
	validate_int(ctrl, 'billable_hours_target');
}

/**
* validate vacation days
* @param	HTMLElement		ctrl
*/
function validate_vacation_days(ctrl){
	if(!validate_int(ctrl, 'vacation_days')){
		return false;
	}

	var value = 
		__getValue('total_personal_days') * 1 + 
		__getValue('total_vacation_days') * 1 + 
		__getValue('total_legal_holidays') * 1;

	if(value / 7 > top.TOTAL_WEEKS){
		var msg = __findErrorMessage('vacation_days_exceed');
		__setErrorState('vacation_days_exceed', msg);
		riseError(msg);

		return false;
	}else{
		__setNormalState('vacation_days_exceed');
	}

	return true;
}
/**
* validate personal days
* @param	HTMLElement		ctrl
*/
function validate_personal_days(ctrl){
	if(!validate_int(ctrl, 'personal_days')){
		return false;
	}

	var value = 
		__getValue('total_personal_days') * 1 + 
		__getValue('total_vacation_days') * 1 + 
		__getValue('total_legal_holidays') * 1;

	if(value / 7 > top.TOTAL_WEEKS){
		var msg = __findErrorMessage('vacation_days_exceed');
		__setErrorState('vacation_days_exceed', msg);
		riseError(msg);

		return false;
	}else{
		__setNormalState('vacation_days_exceed');
	}

	return true;
}

/**
* validate vacation days
* @param	HTMLElement		ctrl
*/
function validate_legal_holidays(ctrl){
	if(!validate_int(ctrl, 'legal_holidays')){
		return false;
	}

	var value = 
		__getValue('total_personal_days') * 1 + 
		__getValue('total_vacation_days') * 1 + 
		__getValue('total_legal_holidays') * 1;

	if(value / 7 > top.TOTAL_WEEKS){
		var msg = __findErrorMessage('vacation_days_exceed');
		__setErrorState('vacation_days_exceed', msg);
		riseError(msg);

		return false;
	}else{
		__setNormalState('vacation_days_exceed');
	}

	return true;
}

/**
* validates break time 
* @param	int		dayNum
*/
function validate_break_time(ctrl, dayNum){
	var value = 
		__getValue('lunch_break_' + dayNum) * 1 +
		__getValue('personal_break_' + dayNum) * 1 +
		__getValue('professional_break_' + dayNum) * 1 +
		__getValue('administrative_break_' + dayNum) * 1 +
		__getValue('dinner_break_' + dayNum) * 1;


	if(value > __getValue('total_hours_in_office_' + dayNum) * 60){
		var msg = __findErrorMessage('break_time_exceed');
		msg = msg.replace('%DAY%', __getCaption(ctrl));

		__setErrorState('break_time_exceed_' + dayNum, msg, ctrl);
		riseError(msg);

		return false;
	}else{
		__setNormalState('break_time_exceed_' + dayNum, ctrl);
	}

	return true;

}

/**
* checks if no errors exists
* @return 	bool
*/
function check_validating(){
	if(top.errors.length == 0){
		return true;
	}

	var msg = "Please correct the following errors before continue:\n\n";
	for(var i = 0; i < top.errors.length; i++){
		msg += (i + 1) + ") " + top.errors[i][1] + "\n";
	}
	alert(msg);

	return false;
}

// END: Validation functions here


// BEGIN: Error messaging here
/**
* Rises error
* @param	String			errText
*/
function riseError(errText){
	alert(errText);
}

/**
* Find constant error message
* @param	String		id
*/
function __findErrorMessage(id){
	for(var i = 0; i < top.errorMessages.length; i++){
		if(top.errorMessages[i][0] == id){
			return top.errorMessages[i][1];

			break;
		}
	}

	return '';
}
// END: Error messaging here




/** 
* Adds a characters before the string to match specified size
* @param	int		size
* @param	char	ch
*/
String.prototype.__addChar = function(size, chr){
	var str = this;
	for(i = str.length; i < size; i++){
		str = chr + str;
	}

	return str;
}

/**
* Removes element from array
* @param	int		i
*/
Array.prototype.__remove = function(i){
	var arr = this;
	if(i < 0 || i >= this.length){
		return arr;
	}

	if(i == 0){
		return arr.slice(1);
	}

	if(i == this.length - 1){
		arr.pop();
		return arr;
	}

	return this.arr(0, i - 1).concat(arr.slice(i + 1));

}
