//  Copyright 2008, 2009 DBIS Research Group at Humboldt-Universität zu Berlin
//
//  This file is part of Researchers Map.
//
//  Researchers Map is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  Researchers Map is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with Researchers Map.  If not, see <http://www.gnu.org/licenses/>.

// File: map.js
// Author: Hannes Muehleisen

// All Markers
var gmarkers = [];

/ Marker movement config */
var circleRadius = 40; // circle radius in pixels
var circleRadiusElements = 30; // Marker movement in pixels
var circleColor = "#245E85";
var circleOpacity = 0.8;
var circleStroke = 4;

var orgpos = [];
var lines = [];
var highlightCircle = null;
var movedMarkers = false;
var lockMarkers = false;

// json result from server
var json = null;

// GMap2 Object
var map = null;
var geocoder = null;

var mtOptions = { padding: 30, color: '#245E85', iconScale: 0.5, weight: 5, length: 14, opacity: 0.5 };

var curTab = null;
var curTabEle = null;
var researchList = false;

var ignoreCache = false;

function initialize() {
	if (GBrowserIsCompatible()) {
		geocoder = new GClientGeocoder();
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl());
		//map.enableScrollWheelZoom();
		map.setCenter(new GLatLng(51.319722, 9.497778), 6); // Kassel im Zentrum ...
		try {
			getMapData(map);
			getResearchData();
		} catch(err) {
			return;
		}
	}
	else {
		alert("Sorry, but your browser is not able to display this application.");
	}
}

function getMapData(map) {
	var url = "callback.php?query=" + encodeURIComponent(mapquery) + uriCacheParam();
	GDownloadUrl(url, function(data, responseCode) {
		if (responseCode != 200) {
			alert("Map query failed. Code: " + responseCode +  " Message:" + data);
		}
		else {
			json = eval('(' + data + ')');
			parseMapResult(json);
		}
	});
}

function parseMapResult(json) {
	for (var x in json.results.bindings) {
		var elem = json.results.bindings[x];
		createMapEntry(map, elem, x);
	}
	document.getElementById("name-list").style.display = "block";
	document.getElementById('shadow').style.display = 'none';
}

function getResearchData() {
	var url = "callback.php?query=" + encodeURIComponent(researchquery) + uriCacheParam();
	GDownloadUrl(url, function(data, responseCode) {
		if (responseCode != 200) {
			alert("Research query failed. Code: " + responseCode +  " Message:" + data);
		}
		else {
			parseResearchResult(data);
		}
	});
}

function parseResearchResult(data) {
	var rjson = eval('(' + data + ')');
	var list = document.getElementById('research');
	list.innerHTML = "";
	var newdiv = document.createElement('div');
	newdiv.innerHTML = '<input class="research-button-submit" type="submit" onclick="return updateMarkers()" value="filter">' + 
					   '<input class="research-button-cancel" type="reset" onclick="return resetMarkers()" value="clear">';
	list.appendChild(newdiv);
	
	for (var x in rjson.results.bindings) {
		var elem = rjson.results.bindings[x];
		var newdiv = document.createElement('div');
		newdiv.className = 'research-entry';
		var label;
		if (elem.label == null) {
			label = elem.i.value.substring(elem.i.value.lastIndexOf("/")+1);
		}
		else {
			label = elem.label.value;
		}
		newdiv.innerHTML = '<input value="' + elem.i.value + '" name="research-interest"  type="checkbox" />' +
						   '<span>' + label + '</span>';
		list.appendChild(newdiv);
	}
	
	researchList = true;
}

function updateMarkers() {
	var list = document.getElementById('research').getElementsByTagName('input');
	var restrictions = [];
	var restricted = false;
	for (var j = 0; j < list.length; j++) {
		var ele = list[j];
		//alert(ele.value);
		if (ele.type == "checkbox" && ele.checked) {
			restrictions.push(ele.value);
			restricted = true;
		}
	}
	
	if (restricted == false) {
		alert("Please select a interest entry");
		return false;
	}
	
	var filter = "";
	for (var j = 0; j < restrictions.length; j++) {
		var ele = restrictions[j];
		filter = filter + " ?i = <" + ele + "> ";
		if (restrictions[j+1] != null) {
			filter = filter + " || "
		}
	}
	
	// show loading, hide list, hide table
	document.getElementById('shadow').style.display = 'block';
	document.getElementById('name-list').style.display = 'none';
	document.getElementById('table').style.display = 'none';
	document.getElementById('table-loading').style.display = 'none';
	
	var url = "callback.php";
	var post = "query=" + encodeURIComponent(filterquery.replace(/DBFILTER/g, filter)) + uriCacheParam();
	
	GDownloadUrl(url, function(data, responseCode) {
		if (responseCode != 200) {
			alert("People query failed. Code: " + responseCode +  " Message:" + data);
		}
		else {
			json = eval('(' + data + ')');
			// clear map
			map.clearOverlays();
			// clear gmarkers
			gmarkers = [];
			// clear list
			document.getElementById('name-list').innerHTML = "";
			//document.getElementById('research-toggle').className = 'research-toggle-active';
			parseMapResult(json);
			
		}
	}, post);
	
	//list.style.display = "none";
	return false;
}


function resetMarkers() {
	var list = document.getElementById('research').getElementsByTagName('input');
	
	//document.getElementById('research-toggle').className = '';
	//list.style.display = "none";
	
	for (var j = 0; j < list.length; j++) {
		var ele = list[j];
		ele.checked = false;
	}
	
	// show loading
	document.getElementById('shadow').style.display = 'block';
	
	// clear map
	map.clearOverlays();
	// clear gmarkers
	gmarkers = [];
	// clear list
	document.getElementById('name-list').innerHTML = "";
			
	getMapData(map);
	return false;
}

var gjson;
function createMapEntry(map, elem, index) {
	if (elem.lat != null) { // we have a gps location
		var point = new GLatLng(elem.lat.value, elem.long.value);
		map.addOverlay(createMarker(point, index, elem));
		createListEntry(elem, index);
	}
	else { // geocode it
		var address = elem.street.value + " " + elem.city.value;
		var url = "geocache.php?query=" + encodeURIComponent(address);
		GDownloadUrl(url, function(data, responseCode) {
			if (responseCode == 200) {
				gjson = eval("(" + data + ")");
				var point = new GLatLng(gjson.Placemark[0].Point.coordinates[1], gjson.Placemark[0].Point.coordinates[0]);
				map.addOverlay(createMarker(point, index, elem));
				createListEntry(elem, index);
			}
		});
	}
	
	
	return;
}

function createListEntry(elem, index) {
	var list = document.getElementById("name-list");
	var newdiv = document.createElement('div');
	newdiv.className = 'name-list-entry';
	newdiv.innerHTML = '<a href="" onclick="openName(' + index + ');return false;">' + getName(elem) + '</a>';
	list.appendChild(newdiv);
}

function createMarker(point, index, elem) {
	// Set draggable markers
	var options = {
		title: getName(elem)
	};

	var marker = new GMarker(point, options);
	marker.content = index;
	gmarkers.push(marker);
	
	//var mt = new MarkerTracker(marker, map, mtOptions);

	GEvent.addListener(marker, "click",
	function() {
		marker.openInfoWindowHtml(makeHTML(marker));
		showPublications(marker.content);
	});

	GEvent.addListener(marker, "mouseover",
	function() {
		moveHiddenMarkers(marker);
	});

	GEvent.addListener(marker, "infowindowclose",
	function() {
		hideDetails();
		document.getElementById('table-header-name').innerHTML = "";
		if (lockMarkers) {
			lockMarkers = false;
			clearMoveMarkers();
		}
		return false;
	});

	GEvent.addListener(marker, "infowindowopen",
	function() {
		lockMarkers = true;
	});
	return marker;
}

function makeHTML(marker) {
	var elem = getEle(marker);
	var html = "<div class='infowindow'>" + getName(elem) + "<br/><a href='" + elem.prof.value + "' target='_new'><img src='layout/SymbolRDF.gif' alt='RDF Data'/> " + elem.prof.value + "</a></div>";
	return html;
}

function openName(id) {
	try {
		for (var j = 0; j < gmarkers.length; j++) {
			marker = gmarkers[j];
			if (marker.content == id) {
				marker.show();
				marker.openInfoWindowHtml(makeHTML(marker));
			}
		}
	} catch(e) {
		}
	
	showPublications(id);
	return false;
}

function showAreaList() {
	if (!researchList) {
		document.getElementById("research").innerHTML = "loading...";
		getResearchData();
	}
	document.getElementById("research").style.display = "block";
}

function toggleTable() {
	if (curTab == null) return false;
	if (curTab == 'pub') {
		showInfo(curTabEle);
		return false;
	}
	if (curTab == 'info') {
		showPublications(curTabEle);
		return false;
	}
}

function showPublications(id) {
	var elem = json.results.bindings[id];
	curTab = 'pub';
	curTabEle = id;
	// hide person list
	document.getElementById("name-list").style.display = "none";
	
	// show loading
	document.getElementById('table-loading').style.display = "block";
	document.getElementById('table-loading').innerHTML = "querying for publications...";
	document.getElementById('table').style.display = "none";
	document.getElementById('table-header-name').innerHTML = getName(elem);
	document.getElementById('table-title-name').innerHTML = "Publications";
	document.getElementById('table-title-uri').href = elem.prof.value;
	
	document.getElementById('table-button-toggle').innerHTML = "Switch to available data";
	
	var url = "callback.php?query=" + encodeURIComponent(pubquery.replace(/DBPROF/g, elem.prof.value)) + uriCacheParam();
	

	GDownloadUrl(url, function(data, responseCode) {
	    if (responseCode != 200) {
	            alert("Publication query failed. Code: " + responseCode +  " Message:" + data);
	    }
	    else {
	            parsePubResult(data);
	    }
	});
}

function parsePubResult(data) {
	var ijson = eval('(' + data + ')');
	
	var list = document.getElementById('table-values-body')
	clearTable(list);
	
	var curYear;
	for (var x in ijson.results.bindings) {
		var elem = ijson.results.bindings[x];
		
		if (curYear == null || curYear != elem.year.value) {
			var newrow = document.createElement('tr');
			var newlabel = document.createElement('td');
			newlabel.className = 'group';
			
			newlabel.innerHTML = elem.year.value;
			newrow.appendChild(newlabel);   
			list.appendChild(newrow);
			curYear = elem.year.value;
		}
		
		var newrow = document.createElement('tr');
		var newlabel = document.createElement('td');
		newlabel.className = 'label';
		newlabel.innerHTML = elem.title.value + '&nbsp;<a href="' + elem.pub.value + '" target="_new"><img src="layout/SymbolRDF.gif" /></a>';
		newrow.appendChild(newlabel);
		/*
		var newlabel = document.createElement('td');
		newlabel.className = 'icon';
		newlabel.innerHTML = '<a href="' + elem.pub.value + '" target="_new"><img src="layout/SymbolRDF.gif" /></a>';
		newrow.appendChild(newlabel);
		*/
						   
		list.appendChild(newrow);
		
	}
	document.getElementById('table-loading').style.display = "none";
	document.getElementById('table').style.display = "block";
}


function showInfo(id) {
	var elem = json.results.bindings[id];
	curTab = 'info';
	curTabEle = id;
	
	document.getElementById('table-loading').style.display = "block";
	document.getElementById('table-loading').innerHTML = "collecting available data...";
	document.getElementById('table').style.display = "none";
	document.getElementById('table-header-name').innerHTML = getName(elem);
	document.getElementById('table-title-name').innerHTML = "All available data";
	
	clearTable(document.getElementById('table-values-body'));
	
	document.getElementById('table-button-toggle').innerHTML = "Switch to publications";
	
// 	var url = "callback.php?query=" + encodeURIComponent(infoquery.replace(/DBPROF/g, elem.prof.value));
	var url = "callback.php?query=" + encodeURIComponent(alldataquery.replace(/DBPROF/g, elem.prof.value)) + uriCacheParam();
	GDownloadUrl(url, function(data, responseCode) {
		if (responseCode != 200) {
			alert("All data query failed. Code: " + responseCode +  " Message:" + data);
		}
		else {
			parseInfoResult(data);
		}
	});
}

function parseInfoResult(data) {
	var ijson = eval('(' + data + ')');
	var list = document.getElementById('table-values-body');

	for (var x in ijson.results.bindings) {
		var elem = ijson.results.bindings[x];
		
		var label;
		if (elem.pLabel == null) {
			if ( elem.p.value.indexOf("#") == -1 ) {
				label = elem.p.value.substring(elem.p.value.lastIndexOf("/")+1);
			}
			else {
				label = elem.p.value.substring(elem.p.value.lastIndexOf("#")+1);
			}
		}
		else {
			label = elem.pLabel.value;
		}
		
		var valueNode;
		if (elem.o == null) {
			label = "is " + label + " of";
			valueNode = elem.s;
		}
		else {
			valueNode = elem.o;
		}
		
		var value;
		if (valueNode.type == "uri") {
			value = "<a href='" + valueNode.value + "' target='_new'>" + valueNode.value + "</a>";
		}
		else {
			value = valueNode.value;
		}
		var newrow = document.createElement('tr');
		var newlabel = document.createElement('td');
		newlabel.className = 'label';
		newlabel.innerHTML = label;
		newrow.appendChild(newlabel);
	
		var newvalue = document.createElement('td');
		newvalue.className = 'value';
		newvalue.innerHTML = value;
		newrow.appendChild(newvalue);
						   
		list.appendChild(newrow);
		
	}
	
	document.getElementById('table-loading').style.display = "none";
	document.getElementById('table').style.display = "block";
}

function hideDetails() {
	document.getElementById('table-header-name').innerHTML = "";
	document.getElementById('table').style.display = "none";
	document.getElementById('table-loading').style.display = "none";
	document.getElementById("name-list").style.display = "block";
	
	for (var j = 0; j < gmarkers.length; j++) {
		var marker = gmarkers[j];
		marker.closeInfoWindow();
	}
	return false;
}

function moveHiddenMarkers(marker) {
	if (movedMarkers) return;

	var mapNormalProj = G_NORMAL_MAP.getProjection();
	var mapZoom = map.getZoom();
	var clickedPixel = mapNormalProj.fromLatLngToPixel(marker.getPoint(), mapZoom);

	var mPoint = marker.getLatLng();
	var moved = false;
	var newPosI = 0.2;
	
	var colCount = 0;
	for (var j = 0; j < gmarkers.length; j++) {
		var curPoint = gmarkers[j].getLatLng();
		if (mPoint.distanceFrom(curPoint) < 10000) {
			colCount++;
		}
	}

	if (colCount < 2) {
		return false;
	}

	for (var j = 0; j < gmarkers.length; j++) {
		var curPoint = gmarkers[j].getLatLng();
		if (mPoint.distanceFrom(curPoint) < 10000) {
			orgpos[j] = curPoint;
			// get new position
			var aRad = 45 * newPosI * (Math.PI / 180);
			var pixelX = clickedPixel.x + circleRadiusElements * Math.cos(aRad);
			var pixelY = clickedPixel.y + circleRadiusElements * Math.sin(aRad);
			var polyPixel = new GPoint(pixelX, pixelY);
			var polyPoint = mapNormalProj.fromPixelToLatLng(polyPixel, mapZoom);
			// move marker
			gmarkers[j].setLatLng(polyPoint);
			// draw line
			var polyline = new GPolyline([mPoint, polyPoint], "#000000", 1, 1);
			lines.push(polyline);
			map.addOverlay(polyline);

			newPosI++;
			moved = true;
		}
	}
	if (moved) {
		movedMarkers = true;
		highlightArea(mPoint);
	}

}

function clearMoveMarkers() {
	if (!movedMarkers) return false;
	if (highlightCircle != null) {
		map.removeOverlay(highlightCircle);
		GEvent.clearNode(highlightCircle);
	}
	for (var j = 0; j < gmarkers.length; j++) {
		if (orgpos[j] != null) gmarkers[j].setLatLng(orgpos[j]);
	}
	for (var j = 0; j < lines.length; j++) {
		map.removeOverlay(lines[j])
	}
	lines = [];
	highlightCircle = null;
	movedMarkers = false;
}

function highlightArea(point) {
	var markerPoint = point;
	var polyPoints = Array();

	if (highlightCircle) {
		map.removeOverlay(highlightCircle);
	}

	var mapNormalProj = G_NORMAL_MAP.getProjection();
	var mapZoom = map.getZoom();
	var clickedPixel = mapNormalProj.fromLatLngToPixel(markerPoint, mapZoom);

	var polyNumSides = 20;
	var polySideLength = 18;

	for (var a = 0; a < (polyNumSides + 1); a++) {
		var aRad = polySideLength * a * (Math.PI / 180);
		var polyRadius = circleRadius;
		var pixelX = clickedPixel.x + polyRadius * Math.cos(aRad);
		var pixelY = clickedPixel.y + polyRadius * Math.sin(aRad);
		var polyPixel = new GPoint(pixelX, pixelY);
		var polyPoint = mapNormalProj.fromPixelToLatLng(polyPixel, mapZoom);
		polyPoints.push(polyPoint);
	}
	// Using GPolygon(points,  strokeColor?,  strokeWeight?,  strokeOpacity?,  fillColor?,  fillOpacity?)
	highlightCircle = new GPolygon(polyPoints, circleColor, circleStroke, circleOpacity, "#000000", 0.0);

	GEvent.addListener(highlightCircle, "mouseout",
	function() {
		if (lockMarkers) return;
		clearMoveMarkers();
	});
	map.addOverlay(highlightCircle);
}

function getEle(marker) {
	var elem;
	var elem = json.results.bindings[marker.content];
	if (elem == null) alert("error finding data for " + marker);
	return elem;
}

function getName(elem) {
	if (elem.name2 != null) if (elem.name2.value != "") return elem.name2.value;
	if (elem.name1 != null) if (elem.name1.value != "") return elem.name1.value;
	return "N.N.";
}

function toggle (item) 
{
   if (document.getElementById(item).style.display == 'block')
   {
     document.getElementById(item).style.display = 'none';
   }
   else 
   {
     document.getElementById(item).style.display = 'block';
   }
   return false;
}

function clearTable (list) {
	while (list.firstChild) list.removeChild(list.firstChild);
}

function toggleCache() {
	ignoreCache = !ignoreCache;
	if (ignoreCache) {
		document.getElementById('cache-checkbox').checked = 'checked';
	}
	else {
		document.getElementById('cache-checkbox').checked = '';
	}
	getResearchData();
	resetMarkers();
}

function uriCacheParam() {
	if (ignoreCache) {
		return "&nocache=true";
	}
	return "";
}

