//gcensus.js contains the client logic for GCensus

var theApp;
var dpi;

function ds_page() {
	return "datasource_xml.php";
}
function sl_page() {
	return "searchlevel_xml_dtree.php"+"?schema="+theApp.schema;
}
function pl_page() {
	return "placelevel_xml.php"+"?schema="+theApp.schema;
}
function sa_page() {
	return "searcharea_xml.php"+"?schema="+theApp.schema+"&userid="+theApp.userid+"&sl_rowid="+theApp.sl_rowid;
}
function p_page() {
	return "place_xml.php"+"?schema="+theApp.schema+"&userid="+theApp.userid+"&sl_rowid="+theApp.sl_rowid+"&sa_rowid="+theApp.sa_rowid+"&pl_rowid="+theApp.pl_rowid;
}
function idb_page() {
	return "infodb_xml_dtree.php"+"?schema="+theApp.schema+"&infodb_table="+theApp.infodb_table+"&infodb_table_type="+theApp.infodb_table_type;
}
function res_page() {
	return "resolution_xml.php"+"?schema="+theApp.schema;
}
function map_page() {
	return "getmap_xml.php"+"?schema="+theApp.schema+"&userid="+theApp.userid+"&infodb_table="+theApp.infodb_table+"&infodb_table_desc="+theApp.infodb_table_desc+"&infodb_col="+theApp.infodb_col+"&infodb_col_desc="+theApp.infodb_col_desc+"&p_rowid="+theApp.p_rowid+"&p_name="+theApp.p_name+"&res_rowid="+theApp.res_rowid;
}

function get_XMLHTTPRequestObject() {
	var xmlhro = false;
	if (window.XMLHttpRequest) {
		xmlhro = new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		xmlhro = new ActiveXObject("Microsoft.XMLHTTP");
	}
	//xmlhro.overrideMimeType("text/xml");
	if (!xmlhro) {
		alert("Your browser is not supported by GCensus. Browsers that are known to work are: Mozilla Firefox v1.0 or greater; MS Internet Explorer 6");
		throw "Unsupported Browser";
	}
	return xmlhro;
}

function init_gcensus() {
	// Userid selection moved into a separate function to facilitate
	// reloading of userid for a new map
	// userid should really be called request id or map id
	theApp = new gcensus_state('');
	var ratio_div = document.getElementById('ratiomarker');
	dpi = ratio_div.offsetLeft;
	get_datasources();
}

function get_userid() {
	// Uses a synchronous xmlhttprequest to fetch a new userid from server
	var xmlhro = get_XMLHTTPRequestObject();
	xmlhro.open("GET","get_userid.php",false);
	xmlhro.send(null);
	return xmlhro.responseText;
}

function get_datasources() {
	var ds_list = document.getElementById("datasource_list");
	//ds_list = document.getElementById("div_op_select");
	var xmlhro = get_XMLHTTPRequestObject();
	xmlhro.open("GET",ds_page(),true);
	xmlhro.onreadystatechange = function()
	{
		if (xmlhro.readyState == 4 && xmlhro.status == 200) {
			var ds_xml_list = xmlhro.responseXML.getElementsByTagName("datasource_list")[0];
			var descs = ds_xml_list.getElementsByTagName("description");
			var schemata = ds_xml_list.getElementsByTagName("schema");
			
			for (var i=0;i<descs.length;i++) {
				var onclick_handler = "javascript:select_datasource(";
				onclick_handler += "'"+schemata[i].firstChild.nodeValue + "',";
				onclick_handler += "'"+descs[i].firstChild.nodeValue;
				onclick_handler += "'); void 0;";

				//onclick_handler = "javascript:alert('blah'); void 0;";
				
				var href = document.createElement("a");
				
				// You may here be wondering why the hell I'm stuffing the "onclick handler"
				// into the href. It's because, for whatever reason, IE6 refuses to handle
				// onclicks IN THIS ONE PLACE. The onclicks in the fake-select work fine...
				href.setAttribute("href",onclick_handler);
				//href.setAttribute("onclick",onclick_handler);
				
				href.appendChild(document.createTextNode(descs[i].firstChild.nodeValue));
				var listitem = document.createElement("li");
				listitem.appendChild(href);
				//alert(listitem.innerHTML);
				ds_list.appendChild(listitem);
				//ds_list.appendChild(href);
			}
			set_instructions_xml(xmlhro);
		}
	}
	
	xmlhro.send(null);
}

function select_datasource(schema,desc)
{
	//alert("Selected schema "+schema);
	theApp.schema = schema;
	theApp.schemadesc = desc;
	theApp.userid = get_userid();
	reset_status_frame();
	add_to_status_frame("Datasource",desc);
	
	get_sl();
	
	return false;
}

function place_dtree_callback(place_data) {
	// Place XML returns to us "name" and "p_rowid" keys
	add_to_status_frame("Place",place_data['name']);
	theApp.p_rowid=place_data['p_rowid'];
	theApp.p_name=place_data['name'];
	return start_infodb_search();
}

function get_sl() {
	var sl_desc_div = document.getElementById("div_op_desc");
	sl_desc_div.innerHTML = "Please select the area in which you'd like to search by navigating the tree below:";
	set_loading_text();
	
	var xmlhro = get_XMLHTTPRequestObject();
	xmlhro.open("GET",sl_page(),true);
	
	set_banner_link(sl_page());
	
	xmlhro.onreadystatechange = function() 
	{
		if (xmlhro.readyState == 4 && xmlhro.status == 200) {
			var dtree = new DynamicTree("div_op_select",place_dtree_callback);
			dtree.addXMLNodes(null,xmlhro.responseXML);
			return false;
		}
	}
	
	xmlhro.send(null);		
}

function infodb_dtree_callback(infodb_data) {
	// InfoDB XML returns to us "table", "column", and "description"
	// TODO: need to get the table description as well
	theApp.infodb_table = infodb_data['table'];
	theApp.infodb_col = infodb_data['column'];
	theApp.infodb_col_desc = infodb_data['description'];
	add_to_status_frame("Data Point",theApp.infodb_col_desc);
	return get_res();
}

function start_infodb_search() {
	var desc_div = document.getElementById("div_op_desc");
	var select_div = document.getElementById("div_op_select");
	desc_div.innerHTML = "Please choose the data (sub)category you want:";
	set_loading_text();

	theApp.infodb_table="infodb_root";
	theApp.infodb_table_type="I";

	set_banner_link(idb_page());

	var xmlhro = get_XMLHTTPRequestObject();
	xmlhro.open("GET",idb_page(),true);
	xmlhro.onreadystatechange = function ()
	{
		if (xmlhro.readyState == 4 && xmlhro.status == 200) {
			var dtree = new DynamicTree("div_op_select",infodb_dtree_callback);
			dtree.addXMLNodes(null,xmlhro.responseXML);
			return false;
		}
	}
	xmlhro.send(null);
	return false;
}

function infodb_recurse() {
	var idb_select = document.getElementById("idb_select");
	return infodb_recurse(idb_select.value,idb_select.options[idb_select.selectedIndex].text);
}

function get_res() {
	var nextPage = res_page();
	var nextFirstOpt = "Select a resolution...";
	
	set_loading_text();
	
	set_banner_link(nextPage);

	var xmlhro = get_XMLHTTPRequestObject();
	xmlhro.open("GET",nextPage,true);
	xmlhro.onreadystatechange = function ()
	{
		return generic_xmlhro_handler(xmlhro,"res_select","get_map",nextFirstOpt);
	}
	xmlhro.send(null);
	return false;
}

function get_map() {
	var res_select = document.getElementById("res_select");
	return get_map(res_select.value,res_select.options[res_select.selectedIndex].text);
}

function get_map(selectedValue,selectedText) {
	selectedValue = unescape(selectedValue);
	selectedText = unescape(selectedText);
	add_to_status_frame("Resolution",selectedText);
	theApp.res_rowid = selectedValue;
	
	var desc_div = document.getElementById("div_op_desc");
	var select_div = document.getElementById("div_op_select");
	desc_div.innerHTML = "Now generating your map...";
	set_loading_text();

	set_banner_link(map_page());

	var xmlhro = get_XMLHTTPRequestObject();
	xmlhro.open("GET",map_page(),true);
	xmlhro.onreadystatechange = function ()
	{
		var desc_div = document.getElementById("div_op_desc");
		var select_div = document.getElementById("div_op_select");
		var xt_opts = document.getElementById("div_extended_opts");
		if (xmlhro.readyState == 4 && xmlhro.status == 200) {
			// Build extended map options
			var opts_html = "<dl><dt>Color scheme</dt> <dd>"+generate_color_select()+"</dl>";
			opts_html += "<dl><dt>Maximum number of bins</dt> <dd>"+generate_bin_input()+"</dd></dl>";
			xt_opts.innerHTML = opts_html;

			// Add extended map show/hide link
			var xtopts_link_html = "<a href=\"about:blank\" onclick=\"return toggle_xtopts_visibility()\">Show/hide advanced mapping options</a>";
			select_div.innerHTML = xtopts_link_html;
			
			// Display link to download map
			var url = xmlhro.responseXML.getElementsByTagName("url")[0].firstChild.nodeValue;
			var mainHTML = "<a href=\"about:blank\" id=\"maplink\" onclick=\"return gen_map_xt_opts('"+url+"',0)\" ";
			mainHTML += "oncontextmenu=\"return gen_map_xt_opts('"+url+"',1)";
			mainHTML += "\"> Click here to download your map</a>\n";
			desc_div.innerHTML = mainHTML;
			
			// Display the instructions
			var instructions = xmlhro.responseXML.getElementsByTagName("instructions");
			set_instructions_xml(xmlhro);
		}
	}
	xmlhro.send(null);
	return false;
}

function gen_map_xt_opts(url,isrightclick) {
	var bintext = document.getElementById("bins").value;
	var numre = /^[0-9]{1,2}$/;
	if (!bintext.match(numre)) {
		alert("Please enter a valid number for the requested number of bins");
		return false;
	}
	var binnum = parseInt(bintext);
	if (binnum < 1 || binnum > 99) {
		alert("Please choose a number of bins between 1 and 99, inclusive");
		return false;
	}
	var coloropts = document.getElementById("mapcolor").elements;
	var i;
	for (i=0;i<coloropts.length && !coloropts[i].checked;i++) {
	}
	if (i < coloropts.length) { //This should always be true
		var val = coloropts[i].value;
		var start = val.substring(0,6);
		var end = val.substring(7,13);
		url+="&startcolor="+start+"&endcolor="+end+"&numbins="+binnum;
		
		// Rewrite the link
		var linkobj = document.getElementById("maplink");
		linkobj.href = url;
		
		// Handle map storage here
		if (!isrightclick) {
			var storedmap_list = document.getElementById("maps_list");
			var href = document.createElement("a");
			href.setAttribute("href",url);
			var description = theApp.infodb_table_desc+": "+theApp.infodb_col_desc+" in "+theApp.p_name+", "+bintext+" bins";
			href.appendChild(document.createTextNode(description));
			var listitem = document.createElement("li");
			listitem.appendChild(href);
			storedmap_list.appendChild(listitem);
		
			location.href=url;
		}
	} else {
		alert("Error - no map color checked!");
	}
	return (isrightclick==1);

}

function generic_xmlhro_handler(xmlhro,selectid,onchange_handler,firstoption) {
	var select_div = document.getElementById("div_op_select");
	if (xmlhro.readyState == 4 && xmlhro.status == 200) {
		// Handle generation of the SELECT box 
		var rd_pair_list = xmlhro.responseXML.getElementsByTagName("rd_pair_list");
		if (rd_pair_list.length != 0 ) {
			rd_pair_list = rd_pair_list[0];
		} else {
			select_div.innerHTML = "<strong>There are no further options for what you have selected. You may want to go back to your previous step and make a different choice.</strong>";
			return;
		}
		var rowids = rd_pair_list.getElementsByTagName("rowid");
		var descs = rd_pair_list.getElementsByTagName("description");
		var realSelect = 0;
		
		var theHTML = "";
		theHTML += generate_select(rowids,descs,selectid,onchange_handler,firstoption,realSelect);
		select_div.innerHTML = theHTML;
		show_select_chrome();
		
		// IE hack to work around lack of max-height
		// Drags CSS stuff (2in) into the code :(
		select_div.style.height="auto";
		if (select_div.clientHeight > 2*dpi) {
			select_div.style.height=2*dpi;
		}
		
		// Auto-select the only option if there is only one
		if (rowids.length == 1) {
			if (realSelect) {
				var theSelect = document.getElementById(selectid);
				// Option 0 is always the "please select a..." option
				theSelect.selectedIndex = 1;
				eval(onchange_handler);
			} else {
				eval(onchange_handler+"('"+rowids[0].firstChild.nodeValue+"','"+descs[0].firstChild.nodeValue+"')");
			}
		} else {
			// Handle the directions
			set_instructions_xml(xmlhro);
		}


	}
}

function generate_select(values,options,selectid,onchange_handler,firstoption,realSelect) {
	var theHTML = "";
	if (realSelect) {
		theHTML += "<form action=\"\"><p>\n";
		theHTML += "<select id=\""+selectid+"\" onchange=\""+onchange_handler+"()\" multiple=\"yes\">\n";
		theHTML += "<option>"+firstoption+"</option>\n";
		for (var i = 0;i<values.length;i++) {
			theHTML += "<option value=\"" + values[i].firstChild.nodeValue;
			theHTML += "\" title=\""+options[i].firstChild.nodeValue;
			theHTML += "\">"+options[i].firstChild.nodeValue;
			theHTML += "</option>\n";
		}
		theHTML += "</select>\n";
		theHTML =+ "</p></form>\n";
	} else {
		// Make a JS/DHTML fake-select box
		var re = new RegExp(" ","g");
		for (var i = 0;i<values.length;i++) {
			var value = values[i].firstChild.nodeValue;
			// Prevent values from wrapping lines
			var desc = options[i].firstChild.nodeValue;
			var nbspdesc = options[i].firstChild.nodeValue.replace(re,"&nbsp;");
			theHTML += "<a onclick=\"return ";
			theHTML += onchange_handler+"('"+escape(value)+"','"+escape(desc)+"')\"";
			theHTML += " href=\"about:blank\" class=\"plainlink\">"+nbspdesc+"</a><br>\n";
		}
	}
	return theHTML;
	
	
}

function set_instructions_text(inst) {
	var dir_span = document.getElementById("span_instructions");
	dir_span.innerHTML = inst;
}

function set_instructions_xml(xmlhro) {
	var directions = xmlhro.responseXML.getElementsByTagName("instructions");
	if (directions.length!=0) {
		set_instructions_text(directions[0].firstChild.nodeValue);
	} else {
		set_instructions_text("");
	}
}

function set_loading_text() {
	var select_div = document.getElementById("div_op_select");
	var xt_opts = document.getElementById("div_extended_opts");
	xt_opts.style.visibility = "hidden";
	hide_select_chrome();
	select_div.innerHTML = "<i>Loading</i><br><br><img src=\"3MA_processingbar.gif\">";
	set_instructions_text("Loading data for the next step. Please be patient - this may take a minute, especially if there are many active users.");
}

function set_banner_link(url) {
	var DEBUG = 0;
	if (DEBUG) {
		var banner_div = document.getElementById("banner");
		banner_div.innerHTML = "<a href=\""+url+"\"> "+url+"</a>";
	}
}

function hide_select_chrome() {
	var select_div = document.getElementById("div_op_select");
	select_div.style.overflow = "hidden";
	select_div.style.border = "0px";
}

function show_select_chrome() {
	var select_div = document.getElementById("div_op_select");
	select_div.style.overflow = "scroll";
	select_div.style.border = "1px solid #000";
}

function add_to_status_frame(step,selection) {
	var status_list = document.getElementById("status_list");
	var status_div = document.getElementById("currentstatus");
	status_div.style.visibility="visible";
	var dt = document.createElement("dt");
	dt.appendChild(document.createTextNode(step));
	var dd = document.createElement("dd");
	dd.appendChild(document.createTextNode(selection));
	status_list.appendChild(dt);
	status_list.appendChild(dd);
}

function reset_status_frame() {
	var status_list = document.getElementById("status_list");
	var status_div = document.getElementById("currentstatus");
	status_div.style.visibility="hidden";
	status_list.innerHTML="";
}

function colorpair(start,end,desc) {
	this.start=start;
	this.end=end;
	this.desc=desc;
}

function generate_color_select() {
	var colors = new Array();
	colors[colors.length] = new colorpair("0000ff","ff0000","Blue to Red");
	colors[colors.length] = new colorpair("cefd57","205b19","Shades of Green");
	colors[colors.length] = new colorpair("000000","ffffff","Black to White");
	var theHTML = "";
	theHTML += "<form id=\"mapcolor\">";
	for (var i=0;i<colors.length;i++) {
		theHTML += "<input type=\"radio\" name=\"color\" value=\""+colors[i].start+"_"+colors[i].end+"\" ";
		if (i==0) {
			theHTML += "checked";
		}
		theHTML += ">"+colors[i].desc+" ";
		theHTML += "<table><tr><td bgcolor=\"#"+colors[i].start+"\"><td bgcolor=\"#"+colors[i].end+"\"></tr></table><br>\n";
	}
	return theHTML;
}
		
function generate_bin_input() {
	var thehtml = "";
	thehtml += "<form id=\"mapbins\">";
	thehtml += "<input type=\"text\" name=\"bins\" id=\"bins\" size=\"2\" maxlength=\"2\" value=\"5\">";
	thehtml += "</form>";
	return thehtml;
}
	
function toggle_xtopts_visibility() {
	var xt_opts = document.getElementById("div_extended_opts");
	if (xt_opts.style.visibility == 'hidden') {
		xt_opts.style.visibility = 'visible';
	} else {
		xt_opts.style.visibility = 'hidden';
	}
	return false;

}
