dojo.require("dojo.io.*");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.Dialog");
// config
var baseurl = "http://debtags.alioth.debian.org/cgi-bin/index.cgi?tags=";
var desturl = "http://debtags.alioth.debian.org/edit.html?pkg=";
var cgiurl = "/cgi-bin/cloud/";
var magicscale = 1;
// state
var selectedtags = [];

/* UI events */
function selectTag(event) {
	selectedtags.push(this.name);
	update();
}

function unselectTag(event) {
	/* unfortunately, I don't know of any "set" type in JavaScript */
	var newtags = [];
	var found = false;
	for (var i=0; i<selectedtags.length; i++) {
		if (selectedtags[i] != this.name) {
			newtags.push(selectedtags[i]);
		} else found = true;
	}
	if (!found) { window.alert("Tag not found: "+this.name); }
	selectedtags = newtags;
	update();
}

function toggleCloud(event) {
	if (!this.expanded) {
		this.expanded = makeCloud(this.span, this, false);
	} else {
		this.expanded.parentNode.removeChild(this.expanded);
		this.expanded = false;
	}
}

function makeCloud(node, tree, facetonly) {
	if (tree.tags.length == 0) {
		node.appendChild(document.createTextNode("No further refinement using tag clouds offered, please choose a package below."));
		return;
	}
	var max = 0;
	for (var i=0; i<tree.tags.length; i++)
		if (tree.tags[i].count > max)
			max = tree.tags[i].count;
	var subtags = document.createElement("span");
	for (var i=0; i < tree.tags.length; i++) {
		var tag = tree.tags[i];
		var size = Math.log(1+magicscale*tag.count/max)/Math.log(magicscale+1)
		size = Math.floor(size*9+.5)
		var isfacet = (tag.tags.length > 0);
		
		if (!isfacet && facetonly) continue;

		var span = document.createElement("span");
		var a = document.createElement("a");
		span.className="tag"+size;
		a.className="tag";
		if (isfacet) a.className = "facet";
		a.appendChild(document.createTextNode(tag.shortname));
		span.appendChild(a);

		tag.span = span

		if (isfacet) {
			dojo.event.connect(a,"onclick",tag,"toggleCloud");
		} else {
			//a.href="http://debtags.alioth.debian.org/cgi-bin/index.cgi?tags="+tag.name;
			dojo.event.connect(a,"onclick",tag,"selectTag");
		}

		subtags.appendChild(span);
		subtags.appendChild(document.createTextNode(" "));
	}
	node.appendChild(subtags);
	return subtags;
}

/* sort by tag name, facets first */
/* when facet handling has become native, this could go away */
function alphasort(a, b) {
	if (b[0].indexOf(a[0]+"::") == 0) return -1;
	if (a[0].indexOf(b[0]+"::") == 0) return 1;
	if (b[0].indexOf(a[0]) == 0) return 1;
	if (a[0].indexOf(b[0]) == 0) return -1;
	if (a[0] < b[0]) return -1;
	if (a[0] > b[0]) return 1;
	return 0;
}

function processTags(data, facets) {
	/* sort data */
	data.sort(alphasort);
	facets.sort(alphasort);

	/* process facets into objects */
	var fobjs = new Array();
	var result = new Array();
	for (var facet in facets) {
		if (!facets[facet][0]) continue;
		var fobj = {
			name: facets[facet][0],
			shortname: facets[facet][0],
			count: facets[facet][1],
			tags: new Array(),
			toggleCloud: toggleCloud
		};
		// insert into array
		fobjs[facets[facet][0]] = fobj;
		result.push(fobj);
	}

	for (var tag in data) {
		if (!data[tag][0]) continue;
		var newtag = {
			name: data[tag][0],
			shortname: data[tag][0],
			count: data[tag][1],
			tags: new Array(),
			selectTag: selectTag
		};
		var pos = newtag.name.indexOf("::");
		if (pos < 0) { dojo.debug("Warning: tag without facet encountered: "+newtag.name); continue; }
		// split
		facet = newtag.name.substring(0,pos);
		newtag.shortname = newtag.name.substr(pos+2);
		if (!fobjs[facet]) {
			dojo.debug("Warning: unknown facet "+facet+" encountered!");
			continue;
		}
		fobjs[facet].tags.push(newtag);
	}
	return result;
}

function showPackages(node, packages, stats) {
	node.innerHTML="";
	if (packages.length == 0) {
		node.appendChild(document.createTextNode(
			stats.totalpkgs + " packages not displayed (please choose additional tags)."));
	} else if (packages.length < stats.totalpkgs) {
		node.appendChild(document.createTextNode(
			(stats.totalpkgs-packages.length) + " packages not displayed (please choose additional tags)."));
	}
	packages.sort(alphasort);
	for (var i=0; i < packages.length; i++) {
		var div = document.createElement("div");
		var a = document.createElement("a");
		a.className="package";
		a.href=desturl+packages[i][0];
		a.appendChild(document.createTextNode(packages[i][0]));
		div.appendChild(a);
		div.appendChild(document.createTextNode(" "+packages[i][1]));
		node.appendChild(div);
	}
}

function showSelected(node, tags) {
	node.innerHTML="";
	for (var i=0; i < tags.length; i++) {
		var obj = {
			name: tags[i],
			unselectTag: unselectTag
		}
		var span = document.createElement("span");
		span.className="tag";
		var a = document.createElement("a");
		a.className="tag_sel";
		a.appendChild(document.createTextNode(tags[i]));
		dojo.event.connect(a,"onclick",obj,"unselectTag");
		span.appendChild(a);
		node.appendChild(span);
		node.appendChild(document.createTextNode(" "));
	}
}

// update after changing selectedtags
function update() {
	dojo.widget.byId("LoadingDialogContent").show();
	var bindArgs = {
		url: cgiurl + selectedtags.join("/"),
		error: function(type, data, evt) { alert("Error while loading data from backend."); },
		mimetype: "text/json"
	};
	var req = dojo.io.bind(bindArgs);
	dojo.event.connect(req, "load", "contentCallBack");
}

function contentCallBack(type,data,evt) {
	var tagcloud = document.getElementById("tagcloud");
	var packages = document.getElementById("packages");
	var seltags = document.getElementById("tags");
	tags = { tags: processTags(data.tags, data.facets) };
	showPackages( packages, data.packages, data.stats );
	showSelected( seltags, data.selected );
	tagcloud.innerHTML = "";
	makeCloud( tagcloud, tags, true);
	dojo.widget.byId("LoadingDialogContent").hide();
}

dojo.addOnLoad(update);
