/**
 * General and form utilities.
 */

// Sets class name for a named element.
function setClass(elementId, className) {
	var element = document.getElementById(elementId);
	element.className = className;
}

// Sets class hide for a named element in given seconds.
function timeHide(elementId, seconds) {
	setTimeout("setClass('" + elementId + "', 'hide');", seconds * 1000);
}

// Sets value for a named input.
function setInputValue(inputId, value) {
	var input = document.getElementById(inputId);
	input.value = value;
}

// Gets value from a named input.
function getInputValue(inputId) {
	var input = document.getElementById(inputId);
	return input.value;
}

// Selects value in a named select.
function setSelectValue(selectId, value) {
	var select = document.getElementById(selectId);
	for(var n = 0; n < select.options.length; n++) {
		if(select.options[n].value == value) {
			select.selectedIndex = n;
			return;
		}
	}
}

// Gets value from a named select.
function getSelectValue(selectId) {
	var select = document.getElementById(selectId);
	return select.options[select.selectedIndex].value;
}

// Selects next value in a named select.
function nextSelectValue(selectId) {
	var select = document.getElementById(selectId);
	if(select.selectedIndex < select.options.length - 1) {
		select.selectedIndex = select.selectedIndex + 1;
	}
}

// Selects previous value in a named select.
function previousSelectValue(selectId) {
	var select = document.getElementById(selectId);
	if(select.selectedIndex > 0) {
		select.selectedIndex = select.selectedIndex - 1;
	}
}

// Checks if checkbox is selected.
function isCheckbox0or1(checkboxId) {
	if(document.getElementById(checkboxId).checked) {
		return 1;
	}
	return 0;
}

// Hides all selects for ie 6 and earlier.
function ie6Check() {
	var i = navigator.userAgent.indexOf("MSIE");
	if(i > 0) {
		if(parseInt(navigator.userAgent.substring(i + 5, i + 6)) < 7) {
			return true;
		}
	}
	return false;
}
function ie6HideSelects(flag) {
	if(ie6Check()) {
		var value = "hidden";
		if(!flag) {
			value = "visible";
		}
		for(var i = 0; i < document.forms.length; i++) {
			for(var j = 0; j < document.forms[i].length; j++) {
				if(document.forms[i].elements[j].options) {
					document.forms[i].elements[j].style.visibility = value;
				}
			}
		}
	}
}

// Adds option to select.
function addOption(selectElement, value, name) {
	var opt = document.createElement('option');
	opt.value = value;
	opt.text = name;
	try {
		selectElement.add(opt, null);
	} catch(ex) {
		selectElement.add(opt);
	}
}

// Generates numeric options to a named select.
function numericOptions(selectId, min, max, selected) {
	var select = document.getElementById(selectId);
	for(var n = min; n <= max; n++) {
		addOption(select, n, n < 10 ? '0' + n : n); 
		if(n == selected) {
			select.selectedIndex = select.options.length - 1;
		}
	}
}

// Generates hour options for days divided at 4:00.
function hourOptionsDiv4(selectId, selected) {
	var select = document.getElementById(selectId);
	for(var n = 4; n <= 27; n++) {
		var nn = n < 24 ? n : n - 24;
		addOption(select, n, nn < 10 ? '0' + nn : nn);
		if(n == selected) {
			select.selectedIndex = select.options.length - 1;
		}
	}
}

// Generates listed options to a named select.
function listOptions(selectId, values, names, selected) {
	if(names == null) {
		names = values;
	}
	var select = document.getElementById(selectId);
	if(selected instanceof Array) {
		for(var n = 0; n < values.length; n++) {
			addOption(select, values[n], names[n]);
			for(var i = 0; i < selected.length; i++) {
				if(values[n] == selected[i]) {
					select.options[select.options.length - 1].selected = true;
					break;
				}
			}
		}
	} else {
		for(var n = 0; n < values.length; n++) {
			addOption(select, values[n], names[n]);
			if(values[n] == selected) {
				select.selectedIndex = select.options.length - 1;
			}
		}
	}
}

// Lists for month options generation.
var monthValues = [1,2,3,4,5,6,7,8,9,10,11,12];
var monthNames = null;

/**
 * Ajax utilities.
 */

// Loads response from an url, callback funtion: cbf(pass, response)
function loadUrl(url, cbf, pass) {
	var request = false;
	if(window.XMLHttpRequest) {
		request = new XMLHttpRequest();
	} else if(window.ActiveXObject) {
		request = new ActiveXObject('Microsoft.XMLHTTP');
	}
	request.onreadystatechange = function() {
		if(request.readyState == 4) {
			cbf(pass, request.responseText);
		}
	}
	request.open('GET', url, true);
	request.send(null);
}

// Loads html from an url to a named element.
function loadHtml(elementId, url) {
	loadUrl(url, loadHtmlCbf, elementId);
}

// Clears html from a named element.
function clearHtml(elementId) {
	loadHtmlCbf(elementId, '');
}

// Sets response to a named element.
function loadHtmlCbf(elementId, response) {
	var element = document.getElementById(elementId);
	element.innerHTML = response;
}

// Loads json object from an url, callback function: cbf(jsonobj)
function loadJson(cbf, url) {
	loadUrl(url, loadJsonCbf, cbf);
}

// Invokes callback function with json object.
function loadJsonCbf(cbf, response) {
	if(response.length > 0) {
		var jsonobj = eval('(' + response + ')');
		cbf(jsonobj);
	}
}

// Looks for an embedded return value in a response.
function parseResponseReturn(response) {
	var ret = null;
	if(response.substr(response.length - 1) == '!') {
		var i = response.lastIndexOf('#');
		if(i > 0) {
			ret = response.substring(i + 1, response.length - 1);
			response = response.substring(0, i);
		}
	}
	return [response, ret];
}

/**
 * Calendar selector.
 */

// Toggles calendar selector, callback functions: [year,month,day] = openCbf(key), selectCbf(key, year, month, day)
function calendarSelector(key, openCbf, selectCbfName) {
	var div = document.getElementById('calendarpop' + key);
	if(div.className == 'hide') {
		div.className = 'calendarpop';
		var initarr = openCbf(key);
		calendarPage(key, selectCbfName, initarr[0], initarr[1], initarr[2]);
		ie6HideSelects(true);
	} else {
		div.className = 'hide';
		ie6HideSelects(false);
	}
}

// Loads generated calendar page.
function calendarPage(key, selectCbfName, year, month, day) {
    loadHtml('calendar' + key, 'ajax_calendarpage.php?key=' + key + '&cbf=' + selectCbfName
    	+ '&year=' + year + '&month=' + month + '&day=' + day);
}

// Finishes calendar selection.
function calendarSelect(key, selectCbf, year, month, day) {
	setClass('calendarpop' + key, 'hide');
	selectCbf(key, year, month, day);
	ie6HideSelects(false);
}

/**
 * Navigation bar calendar cbf.
 */

// List for navi calendar open.
var naviPymd = null;
var naviUrl = 'calendar.php';

// Chooses initial calendar page.
function calendarNaviOpen(key) {
	return [naviPymd[1], naviPymd[2], naviPymd[3]];
}

// Finishes calendar selection.
function calendarNaviSelect(key, year, month, day) {
	url = naviUrl + '?year=' + year + '&month=' + month + '&day=' + day;
	if(naviPymd[0] > 0) {
		url += '&page=' + naviPymd[0];
	}
	window.location.href = url;
}

/**
 * Date selector calendar cbf.
 */

var dateChangeCbf = null;

// Chooses initial calendar page.
function calendarDateOpen(key) {
	return [getSelectValue(key + 'year'), getSelectValue(key + 'month'), getSelectValue(key + 'day')];
}

// Finishes calendar selection.
function calendarDateSelect(key, year, month, day) {
	setSelectValue(key + 'year', year);
	setSelectValue(key + 'month', month);
	setSelectValue(key + 'day', day);
	dateChange(key);
}

// Announces date change.
function dateChange(key) {
	if(typeof dateChangeCbf == 'function') {
		dateChangeCbf(key);
	}
}

/**
 * Color selector.
 */

// Generates color palette.
function colorPalette(key) {
	var html = '';
	var components = ['FF', 'EE', 'CC', '99', '66', '00'];
	for(var a = 0; a < 6; a++) {
		for(var b = 0; b < 6; b++) {
			for(var c = 0; c < 6; c++) {
				var color = components[a] + components[b] + components[c];
				html += '<input type="button" value="&nbsp" onClick="colorSelect(\''
					+ key + '\',\'' + color + '\');" style="background: #' + color + ';" />';
			}
		}
	}
	document.getElementById('colorpop' + key).innerHTML = html;
}

// Updates color field background.
function colorUpdate(key) {
	var input = document.getElementById(key);
	input.style.color = '#444444';
	input.style.background = '#' + input.value;
}

// Toggles color selector.
function colorSelector(key) {
	var div = document.getElementById('colorpop' + key);
	if(div.className == 'hide') {
		div.className = 'colorpop';
	} else {
		div.className = 'hide';
	}
}

// Finishes color selection.
function colorSelect(key, colorstr) {
	setClass('colorpop' + key, 'hide');
	setInputValue(key, colorstr);
	colorUpdate(key);
}

/**
 * Customer selector.
 */

// Initializes customer selector.
function customerInit(key) {
	var id = Number(getInputValue(key));
	if(id > 0) {
		loadHtml(key + 'hits', 'ajax_customersearch.php?key=' + key + '&id=' + id);
	} else {
		clearHtml(key + 'hits');
	}
}

// Updates customer search.
function customerSearch(key, autoselect) {
	if(document.getElementById(key + 'editbs').className != 'hide') {
		return;
	}
	setInputValue(key, 0);
	var name = encodeURIComponent(getInputValue(key + 'name'));
	var url = 'ajax_customersearch.php?key=' + key + '&name=' + name;
	if (!autoselect) {
		url += '&autoselect=0';
	}
	loadUrl(url, customerSearchCbf, key);
}
function customerSearchCbf(key, response) {
	var rar = parseResponseReturn(response);
	if(rar[1] != null) {
		setInputValue(key, Number(rar[1]));
	}
	loadHtmlCbf(key + 'hits', rar[0]);
}

// Resets customer search.
function customerReset(key) {
	clearHtml(key + 'hits');
	setInputValue(key, 0);
	setInputValue(key + 'name', '');
}

// Selects a customer.
function customerSelect(key, id) {
	setInputValue(key, id);
	if(id > 0) {
		loadHtml(key + 'hits', 'ajax_customersearch.php?key=' + key + '&id=' + id);
	} else {
		var name = encodeURIComponent(getInputValue(key + 'name'));
		loadHtml(key + 'hits', 'ajax_customersearch.php?key=' + key + '&name=' + name + '&autoselect=0');
	}
}

// Prepares to create a new customer.
function customerNew(key) {
	setInputValue(key, 0);
	loadHtml(key + 'hits', 'ajax_customersearch.php?key=' + key + '&edit=0');
	setClass(key + 'normbs', 'hide');
	setClass(key + 'editbs', 'showline');
}

// Edits the selected customer.
function customerEdit(key) {
	var id = Number(getInputValue(key));
	loadUrl('ajax_customersearch.php?key=' + key + '&edit=' + id, customerEditCbf, key);
}
function customerEditCbf(key, response) {
	var rar = parseResponseReturn(response);
	if(rar[1] != null) {
		setInputValue(key + 'name', rar[1]);
	}
	loadHtmlCbf(key + 'hits', rar[0]);
	setClass(key + 'normbs', 'hide');
	setClass(key + 'editbs', 'showline');
}

// Saves the changes to edited customer.
function customerSave(key, nameMsg) {
	var name = getInputValue(key + 'name');
	if(name.length == 0) {
		alert(nameMsg);
		return;
	}
	loadUrl('ajax_customersearch.php?key=' + key + '&save=' + Number(getInputValue(key))
		+ '&name=' + encodeURIComponent(name) + '&name2=' + encodeURIComponent(getInputValue(key + 'name2'))
		+ '&phone=' + encodeURIComponent(getInputValue(key + 'phone'))
		+ '&address=' + encodeURIComponent(getInputValue(key + 'address'))
		+ '&postal=' + encodeURIComponent(getInputValue(key + 'postal'))
		+ '&city=' + encodeURIComponent(getInputValue(key + 'city'))
		+ '&email=' + encodeURIComponent(getInputValue(key + 'email'))
		+ '&foreignref=' + encodeURIComponent(getInputValue(key + 'foreignref'))
		+ '&calendarname=' + encodeURIComponent(getInputValue(key + 'calendarname'))
		+ '&field1=' + encodeURIComponent(getInputValue(key + 'field1'))
		+ '&field2=' + encodeURIComponent(getInputValue(key + 'field2'))
		, customerSaveCbf, key);
}
function customerSaveCbf(key, response) {
	var rar = parseResponseReturn(response);
	setInputValue(key, rar[1]);
	loadHtmlCbf(key + 'hits', rar[0]);
	setClass(key + 'normbs', 'showline');
	setClass(key + 'editbs', 'hide');
}

// Cancels the changes to edited customer.
function customerCancel(key) {
	customerInit(key);
	setClass(key + 'normbs', 'showline');
	setClass(key + 'editbs', 'hide');
}

// Checks for unsaved customer.
function customerCheck(key, msg) {
	if(document.getElementById(key + 'editbs').className != 'hide') {
		alert(msg);
		return false;
	}
	return true;
}

/**
 * Entry form.
 */

// Displays and hides repeat view.
function repeatView() {
	var i = document.getElementById('x_repid').selectedIndex;
	if(i > 0 && i < 5) {
		setClass('repeatperiod', 'show');
		if(i == 4) {
			setClass('repeatwdays', 'show');
		} else {
			setClass('repeatwdays', 'hide');
		}
		repeatChanged(null);
	} else {
		setClass('repeatselected', 'hide');
		setClass('repeatperiod', 'hide');
		setClass('repeatwdays', 'hide');
	}
}

// Updates repeat view when selections are changed.
function repeatChanged(key) {
	if(document.getElementById('x_repid').selectedIndex == 0) {
		return;
	}
	var wdays = '';
	for(var n = 0; n < 7; n++) {
		wdays += isCheckbox0or1('x_repwday' + n);
	}
	loadHtml('repeatselected', 'ajax_repeateddays.php?freq=' + getSelectValue("x_repid") + '&skip=' +
		getSelectValue('x_repskip') + '&by=' + getSelectValue('x_rbyear') + '&bm=' + getSelectValue('x_rbmonth')
		+ '&bd=' + getSelectValue('x_rbday') + '&ey=' + getSelectValue('x_reyear') + '&em=' + getSelectValue('x_remonth')
		+ '&ed=' + getSelectValue('x_reday') + '&repwdays=' + wdays);
	setClass('repeatselected', 'tinylist');
}

// Displays stored repeat view.
function storedRepeatView(id, entryrepeat, ext) {
	setClass('repeatselected', 'hide');
	setClass('repeatstored', 'tinylist');
	loadHtml('repeatstored', 'ajax_repeateddays.php?id=' + entryrepeat + '&sel=' + id + '&ext=' + ext);
}

// Displays stored attended view.
function linkAttended() {
	setClass('attended', 'buttons');
}

/**
 * Billing.
 */

// Stored bill from data.
var billfrom = [null,null];

// Changes bill from data.
function changeBillFrom() {
	var n = getSelectValue('x_billfrom') - 1;
	setInputValue('x_myname', decodeURI(billfrom[n][0]));
	setInputValue('x_myaddress', decodeURI(billfrom[n][1]));
	setInputValue('x_mypostal', decodeURI(billfrom[n][2]));
	setInputValue('x_mycity', decodeURI(billfrom[n][3]));
	setInputValue('x_myphone', decodeURI(billfrom[n][4]));
	setInputValue('x_contactperson', decodeURI(billfrom[n][5]));
	setInputValue('x_homemunicipality', decodeURI(billfrom[n][6]));
	setInputValue('x_businessid', decodeURI(billfrom[n][7]));
	setInputValue('x_bankaccount', decodeURI(billfrom[n][8]));
	setInputValue('x_iban', decodeURI(billfrom[n][9]));
	setInputValue('x_bic', decodeURI(billfrom[n][10]));
	setSelectValue('x_template', decodeURI(billfrom[n][11]));
}

// Counts row numbers for bill.
function billCount(idn, fixed, updateTotal) {
	var q = bill2float(getInputValue('x_quantity' + idn));
	var t = (100 + Number(getInputValue('x_tax' + idn))) / 100;
	var p = null;
	var u = null;
	var s = null;
	if(fixed == 1) {
		p = bill2float(getInputValue('x_price' + idn));
		u = p / t;
		s = q * p;
	} else if(fixed == 2) {
		u = bill2float(getInputValue('x_untaxed' + idn));
		p = Math.round(100 * t * u) / 100;
		s = q * p;
	} else {
		s = bill2float(getInputValue('x_sum' + idn));
		if(q > 0) {
			p = Math.round(100 * (s / q)) / 100;
			u = p / t;
			s = q * p;
		} else {
			p = bill2float(getInputValue('x_price' + idn));
			u = p / t;
		}
	}
	setInputValue('x_quantity' + idn, float2shortbill(q));
	setInputValue('x_price' + idn, float2bill(p));
	setInputValue('x_untaxed' + idn, float2bill(u));
	setInputValue('x_sum' + idn, float2bill(s));
	if(updateTotal) {
		billCountTotal(false);
	}
}

// Counts total numbers for bill.
function billCountTotal(updateRows) {
	var untaxed = 0;
	var sum = 0;
	for(var n = 1; n <= getInputValue('x_numoflines'); n++) {
		if(updateRows) {
			billCount(n, 1, false);
		}
		untaxed += bill2float(getInputValue('x_quantity' + n)) * bill2float(getInputValue('x_untaxed' + n));
		sum += bill2float(getInputValue('x_sum' + n));
	}
	setInputValue('x_totaluntaxed', float2bill(untaxed));
	setInputValue('x_totalsum', float2bill(sum));
}

// Gets float for bill string.
function bill2float(str) {
	var number = Number(str.replace(/\,/g, '.'));
	if(isNaN(number)) {
		return 0;
	}
	return Math.round(100 * number) / 100;
}

// Makes bill string for float.
function float2bill(num) {
	if(num == 0) {
		return '';
	}
	var str = String(Math.round(100 * num) / 100);
	var i = str.indexOf('.');
	if(i < 0) {
		str += '.00';
	} else if(i == 0) {
		str = '0' + str;
	} else if(i == str.length - 2) {
		str += '0';
	}
	return str.replace(/\./g, ',');
}

// Makes short bill string for float.
function float2shortbill(num) {
	if(num == 0) {
		return '';
	}
	var str = String(Math.round(100 * num) / 100);
	var i = str.indexOf('.');
	if(i == 0) {
		str = '0' + str;
	}
	return str.replace(/\./g, ',');
}

/**
 * Settings
 */

// Displays and hides attendable view.
function paymentView() {
	var i = document.getElementById('x_payment').selectedIndex;
	if(i == 3) {
		setClass('attendable', 'show');
	} else {
		setClass('attendable', 'hide');
	}
}
