function lookup(dict, key, def)
{
	if (typeof(dict) != "object" || dict == null || typeof(dict[key]) == "undefined")
		return def;
	return dict[key];
}

function formatSeparator(num, separator)
{
	num = num.toString();
	if (separator.length == 0)
		return num;
	var parts = [];
	while (num.length > 3)
	{
		parts.unshift(num.substring(num.length-3));
		num = num.substring(0,num.length-3);
	}
	parts.unshift(num);
	return parts.join(separator);
}

window.debugcount = 0;

function formatNum(num, params)
{
	var debugflag = false;
	window.debugcount += 1;
	if (debugflag) alert("formatting "+num+"\n"+JSON.stringify(params));
	var exceptions = lookup(params, "exceptions", []);
	if (debugflag) alert("exceptions: "+JSON.stringify(exceptions));
	for (var i in exceptions)
	{
		if (num == exceptions[i])
			return num;
	}
	var def = lookup(params, "default", "");
	if (debugflag) alert("default: "+def);
	if (typeof(num) == "undefined" || num == null)
		num = def;
	num = num.toString()
	if (debugflag) alert("num = "+num);
	if (num.length == 0)
		return num;
	var ignore = lookup(params, "ignore", "");
	if (debugflag) alert("ignore: "+ignore);
	for (var i=0; i<ignore.length; i++)
	{
		num = num.replace(ignore.charAt(i),"");
	}
	if (debugflag) alert("num = "+num);
	var places = lookup(params, "places", (num.indexOf(".")==-1)?0:2);
	if (debugflag) alert("places: "+places);
	num = parseFloat(num);
	if (debugflag) alert("num = "+num);
	var negative = (num != (num = Math.abs(num)));
	if (debugflag) alert("ignore: "+ignore);
	if (debugflag) alert("num = "+num);
	var separator = lookup(params, "separator", ",");
	if (debugflag) alert("separator: "+separator);
	if (places == 0)
	{
		num = parseInt(Math.round(num));
		if (debugflag) alert("num = "+num);
		num = formatSeparator(num, separator);
		if (debugflag) alert("num = "+num);
	}
	else if (places == -1)
	{
		var floatPart = num - Math.floor(num);
		var intPart = int(num - floatPart);
		num = formatSeparator(intPart, separator) + '.' + floatPart;
	}
	else
	{
		num = Math.round(num*Math.pow(10,places));
		var floatPart = num%parseInt(Math.pow(10,places));
		if (debugflag) alert("float part = "+floatPart);
		var intPart = parseInt(Math.floor(num/Math.pow(10,places))).toString();
		if (debugflag) alert("int part = "+intPart);
		while (floatPart.toString().length <places)
			floatPart = "0" + floatPart;
		if (debugflag) alert("float part = "+floatPart);
		intPart = formatSeparator(intPart, separator);
		if (debugflag) alert("int part = "+intPart);
		num = intPart + '.' + floatPart;
		if (debugflag) alert("num = "+num);
	}
	var posSign = lookup(params, "posSign", "");
	if (debugflag) alert("posSign: "+posSign);
	var prefix = lookup(params, "prefix", "");
	if (debugflag) alert("prefix: "+prefix);
	var suffix = lookup(params, "suffix", "");
	if (debugflag) alert("suffix: "+suffix);
	if (debugflag) alert("num = "+ ((negative)?"-":posSign)+prefix+num+suffix);
	return ((negative)?"-":posSign)+prefix+num+suffix;
}

//builds an HTML table element with a given report object (see comment in function)
function createTableFromReportDictionary(report)
{
/*
 *report members:
 *	tableColumnFields: list of column names in order
 *	tableTotalFields: list of columns names (each column name will correspond to a column name in 'tableColumnFields')
 *	tableColumnData: list of rows of column data; each row is a dictionary (JSON) where key corresponds to a 'tableColumnFields' element
 *	tableTotalData: a dictionary (JSON) where key corresponds to a 'tableTotalFields' element
 *	tableFieldFormats: a dictionary (JSON) where key corresponds to a 'tableTotalFields' element
 *
*/	
	var t = document.createElement('table');
	var t_head = document.createElement('thead'); //column names
	var t_body = document.createElement('tbody'); //column data
	var t_foot = document.createElement('tfoot'); //total data
//establish thead
	var t_head_row = document.createElement('tr');
	for (var field=0; field<report.tableColumnFields.length; field++)
	{
		var t_head_row_th = document.createElement('th');
		t_head_row_th.innerHTML = report.tableColumnFields[field];
		t_head_row.appendChild(t_head_row_th);
	}
	t_head.appendChild(t_head_row);
//establish tbody

	for (var row=0; row<report.tableColumnData.length; row++)
	{
		var t_body_row = document.createElement('tr');
		for (var column=0; column<report.tableColumnFields.length; column++)
		{
			var t_body_row_td = document.createElement('td');
			var num = report.tableColumnData[row][report.tableColumnFields[column]];
			var format = report.tableFieldFormats[report.tableColumnFields[column]];
			if (typeof(format) == "object")
			{
				num = formatNum(num, format);
				if (typeof(format.bgColor) == "string")
					t_body_row_td.style.backgroundColor = format.bgColor;
				if (typeof(format.textColor) == "string")
					t_body_row_td.style.color = format.textColor;					
			}		
			else if (typeof(format) == "string")
			{
				num = formatNum(num, report.formats[format]);
			}
			t_body_row_td.innerHTML = num;
			t_body_row_td.setAttribute("noWrap","nowrap");
			t_body_row_td.noWrap = true;
			t_body_row.appendChild(t_body_row_td);
		}
		t_body_row.className = "odd";
		t_body.appendChild(t_body_row);
	}

//establish tfoot
	if (typeof(report.tableTotalData[0]) == "undefined")
		report.tableTotalData = [ report.tableTotalData ];
	for (var row=0; row<report.tableTotalData.length; row++)
	{
		var t_foot_row = document.createElement('tr');
		for (var totalColumn=0; totalColumn<report.tableColumnFields.length; totalColumn++)
		{
			var t_foot_row_td = document.createElement('td');
			var fieldFound = false;
			for (var totalSearch=0; totalSearch<report.tableTotalFields.length; totalSearch++)
			{
				if (report.tableTotalFields[totalSearch] == report.tableColumnFields[totalColumn]) { fieldFound = true; break; }
			}
			if (fieldFound)
			{
				var num = report.tableTotalData[row][report.tableColumnFields[totalColumn]];
				var format = report.tableFieldFormats[report.tableColumnFields[totalColumn]];
				if (typeof(format) == "object")
					num = formatNum(num, format);
				else if (typeof(format) == "string")
					num = formatNum(num, report.formats[format]);
				t_foot_row_td.innerHTML = num;
			}
			t_foot_row.appendChild(t_foot_row_td);
		}
		t_foot.appendChild(t_foot_row);
	}
	
	t.appendChild(t_head);
	t.appendChild(t_body);
	t.appendChild(t_foot);
	
	t.className = "itsthetable sortable";
	return (t);
}

