
(function () {

	var currentCriterion = 'browser';
	var defaultValue = '?';

	var rows = {},		// to store created rows for later use
	root,			// the tbody the rows are appended to
	toBeReset = [],		// for tds that are hidden or stretched, should be unhidden and unstretched
	sortedData = [];	// data objects reverse-sorted by number
	
	prepareData();
	createTable();
	createView(currentCriterion);
	
	function prepareData() {
		var criteria = sortableOn.split(',');
		var totalBrowsers = 0;
		var checker = {};
		for (var i=0,data;data=userData[i];i+=1) {
			var dataObject = {};
			var source1 = types[data.type] || {};
			var source2 = browsers[data.browser] || {};
			if (source1.aliasFor) {
				data.type = source1.aliasFor;
				source1 = types[source1.aliasFor] || {};
			}
			for (var j=0,criterion;criterion=criteria[j];j+=1) {
				var value = data[criterion] || source1[criterion] || source2[criterion];
				if (criterion === 'number' && !value) {
					value = 1;
				}
				if (!value) {
					value = defaultValue;
				}
				dataObject[criterion] = value;
			}
			totalBrowsers += dataObject.number;
			var id = data.type +  ' ' + data.browser;
			if (!checker[id]) {
				checker[id] = dataObject;
				sortedData.push(dataObject);
			}
			else {
				checker[id].number += dataObject.number;
			}
		}
		sortedData.sort(function (a,b) {
			var returnValue = a.number - b.number;
			if (returnValue === 0) {
				returnValue = (a.type < b.type)*2 - 1;
			}
			return returnValue;
		});
		document.getElementById('number').innerHTML = totalBrowsers;
	}
	
	function createView(criterion) {
		while (toBeReset.length) {
			toBeReset[0].style.display = '';
			toBeReset[0].className = '';
			if (toBeReset[0].original) {
				toBeReset[0].innerHTML = toBeReset[0].original;
			}
			toBeReset.shift().rowSpan = 1;
		}

		var sorted = sortParties(criterion);

		for (var i=0,currentGroup;currentGroup = sorted[i];i+=1) {
			if (currentGroup.length === 0) continue;
			var row,
				previous,
				criterionTD,
				combinedNumber=0,
				isNumber = (criterion === 'number');
				
			for (var j=0,party;party=currentGroup[j];j+=1) {
				row = createRow(party);
				criterionTD = row[criterion];
				if (criterionTD && !isNumber) {
					criterionTD.style.display = 'none';
					toBeReset.push(criterionTD);
				}
				combinedNumber += party.number;
				if (previous) {
					root.insertBefore(row,previous);
				}
				else {
					root.appendChild(row);
				}
				previous = row;
			}
			row.className += ' separator';
			if (criterionTD && !isNumber) {
				criterionTD.style.display = '';
				criterionTD.rowSpan = currentGroup.length;
				criterionTD.original = criterionTD.innerHTML;
				criterionTD.innerHTML += '<br>(' + combinedNumber + ')';
			}
		}
		row.className = '';
	}

	function createRow(data) {
		var identifier = data.type + ' ' + data.browser;
		if (rows[identifier]) {
			rows[identifier].className = rows[identifier].className.replace(/separator/,'');
			return rows[identifier];
		}
		var tr = document.createElement('tr');
		tr.id = identifier;
		var sortCriteria = sortableOn.split(',');
		for (var i=0;i<sortCriteria.length;i+=1) {
			var td = document.createElement('td');
			td.innerHTML = data[sortCriteria[i]];
			tr[sortCriteria[i]] = td;
			tr.appendChild(td);
		}
		rows[identifier] = tr;
		return tr;
	}

	function sortParties(criterion) {
		if (criterion === 'number') {
			return [sortedData];
		}
		var sortedParties = {};
		var seats = {};
		for (var i=0,ident;ident=sortedData[i];i+=1) {
			var crit = ident[criterion];
			if (!sortedParties[crit]) {
				sortedParties[crit] = [];
				seats[crit] = 0;
			}
			sortedParties[crit].push(ident);
			seats[crit] += ident.number;
		}

		var calcArray = [];
		for (var i in sortedParties) {
			calcArray.push(i);	
		}
		calcArray.sort(function (a,b) {
			var returnValue = seats[a] - seats[b];
			if (returnValue === 0) {
				returnValue = (a < b)*2 -1;
			}
			return returnValue;
		});

		var sortedGroups = [];
		for (var i=0;i<calcArray.length;i+=1) {
			sortedGroups[sortedGroups.length] = sortedParties[calcArray[i]];
		}

		return sortedGroups;

	}

	function createTable() {
		var oldSort = [];

		var table = document.createElement('table');
		table.className = 'politicsData';
		var head = document.createElement('thead');
		var foot = document.createElement('tfoot');
		root = document.createElement('tbody');
		var header = document.createElement('tr');
		var footer = document.createElement('tr');
		
		var sortCriteria = sortableOn.split(',');
		for (var i=0;i<sortCriteria.length;i+=1) {
//			if (sortCriteria[i] === 'undefined') continue;
			createClickableHeader(sortCriteria[i]);
		}

		head.appendChild(header);
		foot.appendChild(footer);
		table.appendChild(head);
		table.appendChild(foot);
		table.appendChild(root);

		document.getElementById('writeroot').appendChild(table);

		function createClickableHeader(text) {
			var th = document.createElement('th');
			var link = document.createElement('a');
			link.href = '#';
			link.innerHTML = text;
			th.appendChild(link);
			var th2 = th.cloneNode(true);
			var link2 = th2.firstChild;
			link.onclick = link2.onclick = function () {
				if (oldSort.length) {
					oldSort[0].className = '';
					oldSort[1].className = '';
				}
				th.className = 'sort';
				th2.className = 'sort';
				currentCriterion = text;
				createView(currentCriterion);
				oldSort = [th,th2];
				return false;
			}
			header.appendChild(th);
			footer.appendChild(th2);
			if (text === currentCriterion) {
				th.className = 'sort';
				th2.className = 'sort';
				oldSort = [th,th2];
			}
		}			
	}
})();
