//------------------------------------------------------------------------
// Global variables.
//------------------------------------------------------------------------

var work;


//------------------------------------------------------------------------
// Initialization.
//------------------------------------------------------------------------

var nameMap  = { "cn":"China", "de":"Germany", "fr":"France", "us":"United States" };
var maxFetch = 10;

// for use on Homer
var engineCGI  = "bin/engine.cgi";
var wordbagCGI = "bin/wordbag.cgi";

// for use on Steinbeck
//var engineCGI  = "engine.cgi";
//var wordbagCGI = "wordbag.cgi";


//------------------------------------------------------------------------
// getAgent() : Create and return a new agent.
//------------------------------------------------------------------------

function getAgent() {

    if (window.XMLHttpRequest)
	return new XMLHttpRequest();
    else if (window.ActiveXObject) {
	try {
	    return new ActiveXObject("Msxml2.XMLHTTP");
	} catch (e) {
	    try {
		return new ActiveXObject("Microsoft.XMLHTTP");
	    } catch (e) {}
	}
    }

    return null;
}


//------------------------------------------------------------------------
// invokeSearch() : Submit the query to the search engine service.
//------------------------------------------------------------------------

function invokeSearch(type) {

    var engine = encodeURIComponent(document.getElementById("engine").value);
    var query  = encodeURIComponent(document.getElementById("query") .value);
    var aCode  = encodeURIComponent(document.getElementById("aCode") .value);
    var bCode  = encodeURIComponent(document.getElementById("bCode") .value);

    work   = new Object();
    work.a = { name:nameMap[aCode], set:new Array(), tally:new Array(), words:1, bar:"aBar", count:0, done:0, total:0 };
    work.b = { name:nameMap[bCode], set:new Array(), tally:new Array(), words:1, bar:"bBar", count:0, done:0, total:0 };

    for (var side in {"a":1, "b":1}) {
	document.getElementById(side + "Word").style.visibility = "hidden";
    }

    var agent = getAgent();
    agent.onreadystatechange = (type == 'text') ? receiveSearch(agent) : receiveImage(agent);
    agent.open("POST", engineCGI, true);
    agent.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    agent.send("query=" + query + "&engine=" + engine + "&ca=" + aCode + "&cb=" + bCode + "&count=100&type=" + type);
}


//------------------------------------------------------------------------
// receiveImage() : Get the search engine results (image search).
//------------------------------------------------------------------------

function receiveImage(agent) {

    return function() {

	if ((agent.readyState == 4) && (agent.status == 200)) {

	    var set   = agent.responseText.split("\n");
	    var aText = "";
	    var bText = "";

	    work.a.total = set[0];
	    work.b.total = set[1];

	    for (var i = 2; i < set.length; ++i) {
		if (set[i].charAt(0) == 'A') {
		    aText += '<img src="' + set[i].substring(2) + '">\n';
		    ++work.a.count;
		} else if (set[i].charAt(0) == 'B') {
		    bText += '<img src="' + set[i].substring(2) + '">\n';
		    ++work.b.count;
		}
	    }

	    var el;
	    el = document.getElementById("aTop");  el.style.visibility = "visible";  el.innerHTML = buildTop(work.a);
	    el = document.getElementById("bTop");  el.style.visibility = "visible";  el.innerHTML = buildTop(work.b);

	    document.getElementById("aBar")   .style.visibility = "hidden";
	    document.getElementById("aBarBox").style.visibility = "hidden";
	    document.getElementById("aWord").innerHTML = aText;
	    document.getElementById("aWord")  .style.visibility = "visible";

	    document.getElementById("bBar")   .style.visibility = "hidden";
	    document.getElementById("bBarBox").style.visibility = "hidden";
	    document.getElementById("bWord").innerHTML = bText;
	    document.getElementById("bWord")  .style.visibility = "visible";
	}
    }
}


//------------------------------------------------------------------------
// receiveSearch() : Get the search engine results (text search).
//------------------------------------------------------------------------

function receiveSearch(agent) {

    return function() {

	if ((agent.readyState == 4) && (agent.status == 200)) {

	    var set = agent.responseText.split("\n");

	    work.a.total = set[0];
	    work.b.total = set[1];

	    for (var i = 2; i < set.length; ++i) {
		if ((set[i].charAt(0) == 'A') && (work.a.count < maxFetch)) {
		    ++work.a.count;
		    work.a.set.push(set[i].substring(2));
		} else if ((set[i].charAt(0) == 'B') && (work.b.count < maxFetch)) {
		    ++work.b.count;
		    work.b.set.push(set[i].substring(2));
		}
	    }

	    var el;

	    el = document.getElementById("aTop");  el.style.visibility = "visible";  el.innerHTML = buildTop(work.a);
	    el = document.getElementById("bTop");  el.style.visibility = "visible";  el.innerHTML = buildTop(work.b);

	    for (var side in {"a":1, "b":1}) {
		document.getElementById(side + "Bar")   .style.width           = "0%";
		document.getElementById(side + "Bar")   .style.backgroundColor = "red";
		document.getElementById(side + "Bar")   .style.visibility      = "visible";
		document.getElementById(side + "BarBox").style.visibility      = "visible";
		document.getElementById(side + "Word")  .style.visibility      = "visible";
	    }

	    invokeFetch(work.a);
	    invokeFetch(work.b);
	}
    }
}


//------------------------------------------------------------------------
// buildTop() : Build a meaningful string for the table top.
//------------------------------------------------------------------------

function buildTop(country) {

    var suffix = (country.total == 1) ? '' : 's';

    return "<span class='country'>" + country.name  + "</span>" +
	   "<span class='text'>: About </span>" +
	   "<span class='count'>" + country.total + "</span> " +
	   "<span class='text'>result" + suffix + " (Fetching first </span>" +
  	   "<span class='count'>" + country.count + "</span>" +
	   "<span class='text'> unique)</span>";
}


//------------------------------------------------------------------------
// invokeFetch() : Generate a request for the next bag of words.
//------------------------------------------------------------------------

function invokeFetch(country) {

    if (country.set.length > 0) {
	var agent = getAgent();
	agent.onreadystatechange = receiveFetch(agent, country);
	agent.open("POST", wordbagCGI, true);
	agent.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	agent.send("url=" + encodeURIComponent(country.set.pop()));
    }
}


//------------------------------------------------------------------------
// receiveFetch() : Parse a bag of words once it's been received.
//------------------------------------------------------------------------

function receiveFetch(agent, country) {

    return function() {

	if ((agent.readyState == 4) && (agent.status == 200)) {

	    var set = agent.responseText.split("\n");

	    if (set[0] == "success") {

		for (var i = 1; i < set.length; ++i) {

		    if (stopword[set[i]] == 1)
			continue;

		    var word = "_" + set[i];
		    if (country.tally[word] == undefined)
			country.tally[word] = 1;
		    else
			country.tally[word] += 1;
		    ++country.words;
		}

		updateDisplay();
	    }

	    ++country.done;
	    document.getElementById(country.bar).style.width = Math.round(100 * country.done / country.count) + "%";

	    if (country.done >= country.count)
		document.getElementById(country.bar).style.backgroundColor = "green";
	    else
		invokeFetch(country);
	}
    }
}


//------------------------------------------------------------------------
// updateDisplay() : Update the display based on the current tallies.
//------------------------------------------------------------------------

function sortHelper(x) {
    return function(a, b) {
	return x[b] - x[a];
    };
}

function updateDisplay()
{
    var aSet = new Array();  var aKey = new Array();  var aMin;
    var bSet = new Array();  var bKey = new Array();  var bMin;
    var other;

    for (var x in work.a.tally) {
	if (work.a.tally[x] > 1) {
	    other = (work.b.tally[x] == undefined) ? 1 : work.b.tally[x];
	    aSet[x] = (work.a.tally[x] / work.a.words) / (other / work.b.words) - 1;
	    aKey.push(x);
	}
    }
    aKey.sort(sortHelper(aSet));
    aKey = aKey.slice(0, 50);
    aMin = aSet[aKey[aKey.length - 1]];
    aKey.sort();

    for (var x in work.b.tally) {
	if (work.b.tally[x] > 1) {
	    other = (work.a.tally[x] == undefined) ? 1 : work.a.tally[x];
	    bSet[x] = (work.b.tally[x] / work.b.words) / (other / work.a.words) - 1;
	    bKey.push(x);
	}
    }
    bKey.sort(sortHelper(bSet));
    bKey = bKey.slice(0, 50);
    bMin = bSet[bKey[bKey.length - 1]];
    bKey.sort();

    var aText = "";
    var bText = "";
    var size;

    for (var i = 0; i < aKey.length; ++i) {
	size = 8 + Math.round(0.50 * (aSet[aKey[i]] - aMin));
	if (size > 30) size = 30;
	aText += '<span style="font-size: ' + size + 'pt;">' + aKey[i].substring(1) + '</span>\n';
    }

    for (var i = 0; i < bKey.length; ++i) {
	size = 8 + Math.round(0.50 * (bSet[bKey[i]] - bMin));
	if (size > 30) size = 30;
	bText += '<span style="font-size: ' + size + 'pt;">' + bKey[i].substring(1) + '</span>\n';
    }

    document.getElementById("aWord").innerHTML = aText;
    document.getElementById("bWord").innerHTML = bText;
}


function log(x) {
    document.getElementById("debug").innerHTML += x + "<br>";
}
