﻿// GLOBAL VARIABLES
var photoData;
var timelineMode = 'monthly';
var monthNames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');

// Map variables
var map;
var geoXml; 
var geocoder;
var toggleState = 1;
var polygons = [];
var visiblePolygons = 0;
var availablePolygons = 0;
var clickablePolygons = new Array('23424781', '23424909', '23424975', '23424819');
var displayMax = 15;
var delayedUpdate;
var activeMarker;
var yellowIcon;
var icon;

// Map colorsettings
var cNormal = '#ffffff';
var cSelected = '#ffff00';
var cOver = '#ffff80';
var cVisited = '#fa2b48';
var cOutline = '#ffffff';
var cOutlineSelected = '#ff0000';
var cScale = new Array('#ffff97', '#fbf228', '#f2cc26', '#e28c16', '#cc3300'); //'#ffff97', '#fbf228', 

//  Thumbnail sizes & Viewer settings
var szNormal 			= 7;
var szSmall  			= 7;
var szFull   			= 60;
var totIncrement		= -910;
var increment			= 70;
var maxRightIncrement	= increment*(-13);
var positions			= 10;
var openThumbs = new Array();

// When DOM is available
$(document).ready(function(){

	// Turn on preloader for loading behind the scenes
	toggleMainPreloader();
	// Hide (warning) message box
	$('#message').hide();
	// Set most recent month as active
	setMonth();
	// Turn on accordion functionality
	activateAccordion();
	// Hide map overlay
	hideMapOverlay();
	// Focus on first field
	$('#country_from').focus();
	
	//-----------------------------------------------
	// ADD AJAX ERROR HANDLER / VIEWER - FOR DEVELOPMENT ONLY 
	$(document).ajaxError(function(){
		if (window.console && window.console.error) {
			console.error(arguments);
		}
	});	

	//-----------------------------------------------
	// EVENT for the toggle map overlay button
	$("#map_overlay_close").click(function () {
		// When overlay is closed, open it
		if ( $("#map_overlay").css('marginLeft') == '-260px' ) {
			$("#map_overlay").animate({marginLeft: 0}, 1000 );
		}
		// When overlay is open, close it
		else {
			$("#map_overlay").animate({marginLeft: -260}, 1000 );
		}
	});

	//-----------------------------------------------
	// FOCUS on first the month
	$("#monthsList").animate({ 
		marginLeft: maxRightIncrement
	}, 0 );
	$(".overlay").animate({ 
		marginLeft: maxRightIncrement+5
	}, 0 );
	

	//-----------------------------------------------
	// EVENT for the submit search button
	$("#search").submit(function() {		
		initViewUpdate();		
		return false;
	});

	//-----------------------------------------------
	// EVENTS for the timline's previous button
	$("#previous").click(function(){
		if ( photoData == undefined ) {
			// Not supported
			displayMessage("Whooops!", "There are no photos to show you, try searching for something else");
		}
		else {
			if(totIncrement<(increment*(12))){
				if (delayedUpdate != undefined){
					clearTimeout(delayedUpdate);
				}
				// Toggle viewer off
				turnMonthViewerOff();
				// Move the months	
				totIncrement = totIncrement+increment;
				$(".overlay").animate({ 
					marginLeft: totIncrement+5
				}, 400 );

				$("#monthsList").animate({ 
					marginLeft: totIncrement
				}, 400, function() {
					setMonthDown();
					date = $("#monthsList li.active").attr("id").split("-");				
					delayedUpdate = setTimeout("updateMap(photoData, date[1], date[0])", 1000);
				} );			
			}
			return false;
		}
	});

	//-----------------------------------------------
	// EVENTS for the button "next"
	$("#next").click(function(){
		if ( photoData == undefined ) {
			// Not supported
			displayMessage("Whooops!", "There are no photos to show you, try searching for something else");
		}
		else {
			if(totIncrement>maxRightIncrement+4){
				if (delayedUpdate != undefined){
					clearTimeout(delayedUpdate);
				}
				// Toggle viewer off
				turnMonthViewerOff();
				// Move the months	
				totIncrement = totIncrement-increment;
				$(".overlay").animate({ 
					marginLeft: totIncrement+5
				}, 400 );
				
				$("#monthsList").animate({ 
					marginLeft: totIncrement
				}, 400, function() {
					setMonthUp();
					date = $("#monthsList li.active").attr("id").split("-");				
					delayedUpdate = setTimeout("updateMap(photoData, date[1], date[0])", 1000);
				} );			
			}
			return false;
		}
	});
	
	//-----------------------------------------------
	// EVENTS for temperature checkbox
	$("#temperature").click(function(){
		toggleOverlay('temperature');
		$(this).toggleClass("active");
		return false;
	});	
	
	//-----------------------------------------------
	// EVENTS for temperature checkbox
	$("#sunshine").click(function(){
		toggleOverlay('sunshine');
		$(this).toggleClass("active");
		return false;
	});	
	
	initMap();
});


/**
* Load the Google Map
* 
*/
function initMap() {

	if (GBrowserIsCompatible()) {
		// Create map instance
		map = new GMap2(document.getElementById("map_canvas")); 
		// Get the list of map types      
		var mt = map.getMapTypes();
		// Overwrite the getMinimumResolution() and getMaximumResolution() methods
		for (var i=0; i<mt.length; i++) {
			mt[i].getMinimumResolution = function() {return 2;}
			mt[i].getMaximumResolution = function() {return 4;}
		}

		// Geocoder
		geocoder = new GClientGeocoder();
		
		// Base icon
		var baseIcon = new GIcon();
		baseIcon.iconSize = new GSize(32, 32);
		baseIcon.shadowSize = new GSize(56, 32);
		baseIcon.iconAnchor = new GPoint(16, 32);
		baseIcon.infoWindowAnchor = new GPoint(16, 0);
		var iconLocation = "http://maps.google.com/mapfiles/ms/icons/orange-dot.png"
		var iconShadow = "http://maps.google.com/mapfiles/ms/icons/msmarker.shadow.png";
		icon = new GIcon(baseIcon, iconLocation , null, iconShadow );
		
		// Now get the countries
		loadCountries();
		// Set initial map center
		map.setCenter(new GLatLng(24.0875,20.8988889), 2); 
		// Set map controls to a fancier one
		map.addControl(new GLargeMapControl3D());
		// The allowed region which the whole map must be within
		var allowedBounds = new GLatLngBounds(new GLatLng(-30.17934297928927, -8.8125), new GLatLng(63.22669969306126, 34.296875));
		// Add a move listener to restrict the bounds range
		GEvent.addListener(map, "move", function() {
			checkBounds();
		});

		GEvent.addListener(map, 'click', function(overlay, point) {
			if (overlay) {
				map.setCenter(point);
			}
		});

		// Remove active marker when infowindow is closed to make sure no markers remain on map
		GEvent.addListener(map, "infowindowclose", function() {
			map.removeOverlay(activeMarker);
		});

		// If the map position is out of range, move it back
		function checkBounds() {
			// Perform the check and return if OK
			if (allowedBounds.contains(map.getCenter())) {
				return;
			}
			// It`s not OK, so find the nearest allowed point and move there
			var C = map.getCenter();
			var X = C.lng();
			var Y = C.lat();
			var AmaxX = allowedBounds.getNorthEast().lng();
			var AmaxY = allowedBounds.getNorthEast().lat();
			var AminX = allowedBounds.getSouthWest().lng();
			var AminY = allowedBounds.getSouthWest().lat();

			if (X < AminX) {X = AminX;}
			if (X > AmaxX) {X = AmaxX;}
			if (Y < AminY) {Y = AminY;}
			if (Y > AmaxY) {Y = AmaxY;}

			map.setCenter(new GLatLng(Y,X));
		}
	}
}


/**
* Load country overlays onto the Google Map
* 
*/
function loadCountries() {
	var xmlhttp=null;

	if (window.XMLHttpRequest)
	{// code for all new browsers
		var xmlhttp=new XMLHttpRequest();
	}
	else if (window.ActiveXObject)
	{// code for IE5 and IE6
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}

	if (xmlhttp) {
		xmlhttp.open("GET", "http://www.ronkok.com/work/infvis/pub/includes/countries.xml",true);
		xmlhttp.onreadystatechange=function() {
			if (xmlhttp.readyState==4) {
				if (xmlhttp.status == 200) {
					// Get data from response
					var xmldata = GXml.parse(xmlhttp.responseText);
					// Get country information & count available countries/polygons
					var countries = xmldata.documentElement.getElementsByTagName("country");
					availablePolygons = countries.length;
					// For each country, get the polygon coordinates
					for ( var y = 0 ; y < countries.length ; y++ ){
						var points = countries[y].getElementsByTagName("punt");
						var pnts = new Array()
					for (var i = 0; i < points.length; i++) {
							pnts[i] = new GLatLng(parseFloat(points[i].getAttribute("lng")), parseFloat(points[i].getAttribute("lat")));
						}
						polygons[countries[y].getAttribute('name')] = new GPolygon(pnts,cOutline,1,1,cNormal,0.7,{clickable:true});
					} 
					// Get the first polygon
					var firstPolygon;
					for (var polygon in polygons) {
						firstPolygon = polygon;
						break;
					}
					// Start drawing country polygons on map (will ignite the rest)
					addNewPolygon(firstPolygon);
				}
			}			
		}
		xmlhttp.send(null);
	}
}

/**
* Add EVENTS to the timeline's thumbnails
* 
*/
function addThumbEvents(){

	// Mouse leave event on stage, shrink thumbs on mouse leave
	$(".thumbs").mouseleave(function(){
		$(".thumb").animate({ 
			height: szNormal
		}, 300 );
		openThumbs = [];
	});

	// Mouse over event on thumb, enlarge on mouse over & shrink the rest
	$(".thumb").each(function(thumb, i) {
		$(this).mouseover(function(){
			openThumbs.push(this);
			$(this).animate({ 
				height: szFull
			}, 50 );

			for (var j = 0; j < openThumbs.length; j++) {
				if ( i != openThumbs[j] ) {
					$(openThumbs[j]).animate({ 
						height: szNormal
					}, 50 );
					openThumbs.splice(openThumbs.indexOf(openThumbs[j]), 1);
					j--;
				}
			}
		});

		// Mouse out event on thumb, shrink on mouse out
		$(this).mouseout(function(){		
			$(this).animate({ 
				height: szNormal
			}, 500 );
			$(this).stop()
		});
	});
}

/**
* Initiate timeline update, make AJAX call with search parameters
* 
*/
function initViewUpdate() {
	// Get variables
	removeMarker();

	var countryFrom = $("#country_from").val();
	var countryIn = $("#country_in").val();
	var lookingFor = $("#looking_for").val();

	if ( countryFrom == '00000000' && countryIn == '00000000' && lookingFor == '') {
		// No variables provided
		displayMessage("Huh?", "Please be more specific by telling us what you're looking for");
	}
	else if ( countryIn == '00000000' && lookingFor == '') {
		// Not supported
		displayMessage("Sorry!", "This operation is currently not supported");
	}
	else {
		// Create URL
		var retrievalUrlT = "http://www.ronkok.com/work/infvis/pub/includes/retrieve.php?";
		retrievalUrlT = retrievalUrlT+"countryfrom="+countryFrom+"&lookingfor="+lookingFor+"&countryin="+countryIn;
	
		// Temp set field with URL for testing
		$("#querystring").val(retrievalUrlT);
	
		// Make AJAX call for photo data
		$.ajax({
			url: retrievalUrlT,
			type: 'GET',
			dataType: 'json',
			timeout: 120000,
			error: function(){
				displayMessage('Whooops!', 'Something went wrong while retrieving the data');
			},
			success: function(data){
				photoData = data;
				
				if ( photoData.result.results != 0 ) {
					display(photoData);
				}
				else {
					displayMessage('Yoinks!', 'There is nothing in store for you...');
				}
			} 
		});

		// Clear thumbnails
		resetThumbnails();	
		// Reset all countries
		resetVisitingCountries();
		resetSelectedCountries();
	}
}


/**
* Update the timeline
* 
*/
function display(data) {

	// Get display properties
	var ownersMax = data.statistics.owners_max;
	var photosMax = data.statistics.photos_max;
	var ownersMin = data.statistics.owners_min;
	var scale = positions / ownersMax;

	var countriesMapped = 0;

	// When timelineMode is 'overall', display statistics for all months
	if ( timelineMode == 'overall' ) {

		// Highlight visiting countries on the map
		$.each(data.statistics.countries, function(c, country) {
			if ( countriesMapped >= displayMax ) {
				return false;
			}
			else {
				var result = showVisitors(c);
				if (result == true) {
					countriesMapped++;
				}
			}
		}); 
	}
	// When timelineMode is 'monthly', display statistics for specific month
	else {
		updateMap(data, 2009, 2);
	}

	// Walk through years i
	$.each(data.years,function(y,year) {

		// Walk through the available months
		$.each(year, function(m,month)  {

			var owners = [];
			var countPositions = 0;
			var countPhotos = parseInt(month.length);
			var countOwners = 0;

			// Walk through the available photos
			$.each(month, function(p,photo)  {				
				if ( owners[photo.photo_owner] ) {

					if ( parseInt(owners[photo.photo_owner].photo_views) < parseInt(photo.photo_views )) {
						owners[photo.photo_owner] = photo;
					}
				}
				else {				
					owners[photo.photo_owner] = photo;
				}
			});

			//  Workaround for this strange problem
			for (pic in owners) {
				countOwners++;
			}

			// Display unique photographers most viewed photo
			for (pic in owners) {
				
				if ( countPositions <= Math.ceil(countOwners * scale) ) {
					var photo = owners[pic];	
					var img = "http://farm"+photo.photo_farm+".static.flickr.com/"+photo.photo_server+"/"+photo.photo_guid+"_"+photo.photo_secret+"_s.jpg";
					var li = document.createElement('li');
					li.setAttribute('class', 'thumbholder');
					var im = document.createElement('img');
					im.src = img;
					im.setAttribute('id', photo.photo_guid);
					im.setAttribute('class', 'thumb');
					im.setAttribute('width', '50px');
					im.setAttribute('height', '50px');
					li.appendChild(im);
					var target = $('#'+m+'-'+y).find('.thumbs');
					target.append(li);
					addThumbClick(photo);
					countPositions++;
				}
				else {
					break;
				}
			}
		});	
	});
	addThumbEvents();	
}


/**
* Update the map
* 
*/
function updateMap(data, yearS, monthS) {

	// Get variables
	var countryFrom = $("#country_from").val();
	var countryIn = $("#country_in").val();
	var lookingFor = $("#looking_for").val();

	var countries;
	var countriesMapped = 0;

	resetVisitingCountries();
	resetSelectedCountries();

	if ( countryIn == '00000000' && lookingFor != '') {
		// Only color the visited countries
		countries = ownersPerVisitedCountry(data, monthS, yearS);
	}
	else {
		// Retrieve sorted list of visitors per country	
		countries = ownersPerCountry(data, monthS, yearS);
	}

	// First determine top value
	var top = 0;

	for(year in countries) {
		// For each month in the current year
		for (month in countries[year]) {
			// For each country in the current month
			for ( country in countries[year][month] ) {				
				if ( countriesMapped >= displayMax ) {
					break;
				}
				else {					
					//  And if it's a country that can be displayed as visiting
					if ( polygons[country] != undefined ) {						
						// Store highest
						var uniqueVisitors = countries[year][month][country];
						if ( countriesMapped == 0 ) {
							top = uniqueVisitors;				
						}
						else if ( top < uniqueVisitors ) {
							top = uniqueVisitors;
						}	
						countriesMapped++;
					}
				}
			}
		}
	}
	//  Reset mapped
	countriesMapped = 0;

	for(year in countries) {
		// For each month in the current year
		for (month in countries[year]) {
			// For each country in the current month
			for ( country in countries[year][month] ) {

				if ( countriesMapped >= displayMax ) {
					break;
				}
				else {
					//  And if it's a country that can be displayed as visiting
					if ( polygons[country] != undefined ) {	
						var uniqueVisitors = countries[year][month][country];

						var cIndex;

						for ( var i = 1; i <= cScale.length; i++ ) {
							if ( uniqueVisitors <= ((top/cScale.length)*i) ) {
								cIndex = i-1;
								break;											
							}
						}
						showVisitors(country, cIndex);
						countriesMapped++;
					}
				}
			}
		}
	}
	// Adjust max in map scale legend
	$('#scale_max').text(top);
}


/**
* Update the map when a country is selected on the map
* 
*/
function updateMapOnSelect(data, yearS, monthS, countryId) {

	// Get variables
	var countryFrom = $("#country_from").val();
	var countryIn = $("#country_in").val();
	var lookingFor = $("#looking_for").val();

	var countries;
	var countriesMapped = 0;
	var totalVisitors = 0;

	if ( countryIn == 00000000 ) {
		resetVisitingCountries()

		// Select from the data the items we need based on the country
		countries = ownersPerSelectedCountry(data, monthS, yearS, countryId);

		// Determine the total number of photos made in the selected country
		var totalPhotos = photosPerSelectedCountry(data, monthS, yearS, countryId);
		// Get the url for the overlay chart
		var chartUrl = photosPerHour(data, monthS, yearS, countryId);

		// Walk through the years
		var top = 0;

		for(year in countries) {
			// For each month in the current year
			for (month in countries[year]) {
				// For each country in the current month
				for ( country in countries[year][month] ) {				
					if ( countriesMapped >= displayMax ) {
						break;
					}
					else {					
						//  And if it's a country that can be displayed as visiting
						if ( polygons[country] != undefined ) {						
							// Store highest
							var uniqueVisitors = countries[year][month][country];
							if ( countriesMapped == 0 ) {
								top = uniqueVisitors;				
							}
							else if ( top < uniqueVisitors ) {
								top = uniqueVisitors;
							}	
							countriesMapped++;
						}
					}
				}
			}
		}

		countriesMapped = 0;

		for(year in countries) {
			// For each month in the current year
			for (month in countries[year]) {
				// For each country in the current month
				for ( country in countries[year][month] ) {

					if ( countriesMapped >= displayMax ) {
						break;
					}
					else {

						//  And if it's a country that can be displayed as visiting
						if ( polygons[country] != undefined ) {	
							var uniqueVisitors = countries[year][month][country];
							totalVisitors = totalVisitors + uniqueVisitors;

							var cIndex;

							for ( var i = 1; i <= cScale.length; i++ ) {
								if ( uniqueVisitors <= ((top/cScale.length)*i) ) {
									cIndex = i-1;
									break;											
								}
							}
							showVisitors(country, cIndex);
							countriesMapped++;
						}
					}
				}
			}
		}

		// Adjust max in map scale legend
		$('#scale_max').text(top);
		$('#scale_max').effect("highlight", {color: '#ffff33'}, 3000);

		// Update map overlay information
		updateCountryInfoForVisited(countryId, totalVisitors, countriesMapped, totalPhotos, chartUrl);

		// Provide selected country with border?
		showSelected(countryIn);
	}
	// Information about the number of visitors coming from this country to countryIn
	else {

		var chartUrl = photosPerHour(data, monthS, yearS, countryIn, countryId);
		var info = infoFromSelectedCountry(data, monthS, yearS, countryIn, countryId);
		var visitors = info['visitors'];
		var photos = info['photos'];

		updateCountryInfoForVisiting(countryIn, countryId, visitors, photos, chartUrl);
	}
}


/**
* Retrieves an array with countries & the number of their unique visitors
* 
*/
function ownersPerCountry(data, monthS, yearS) {
	
	var sortedCountries = new Object();	
	
	if(!monthS) {
		var monthS = "all";
	}
	if(!yearS) {
		var yearS = "all";
	}
	
	// Initialize countries array
	var ownersPerCountry = new Array();
	
	// Walk through years i
	$.each(data.years,function(y,year) {
		
		// If a year is given, only use data for this year. Else use all years
		if ( y == yearS || yearS == 'all' ) {
		
			// Walk through the available months
			$.each(year, function(m,month)  {
				
				// If a month is given, only use data for this month. Else use all months
				if ( m == monthS || monthS == 'all' ) {
				
					var visitors = new Array();
					var visitorsPerCountry = new Object();;

					// Walk through the available photos
					$.each(month, function(p,photo)  {				

						// When the owner is unknown / not seen before
						if ( jQuery.inArray(photo.photo_owner, visitors) == -1 ) {

							// Add the owner
							visitors.push(photo.photo_owner);

							// When the country does not exist yet
							if ( visitorsPerCountry[photo.photo_ownercountryid]==undefined ) {
								visitorsPerCountry[photo.photo_ownercountryid] = 1;
							}
							// When the country already exists
							else {
								visitorsPerCountry[photo.photo_ownercountryid]++;
							}
						}
					});
					// Sort the array on the number of unique visitors
					if(sortedCountries[y]==undefined){
						sortedCountries[y] = new Object();
					}
					sortedCountries[y][m] = sortCountriesByVisitors(visitorsPerCountry);			
				}
			});
		}
	});

	return sortedCountries;
}


/**
* Retrieves an array with countries & the number of their unique visitors
* 
*/
function ownersPerVisitedCountry(data, monthS, yearS) {

	var sortedCountries = new Object();	
	
	if(!monthS) {
		var monthS = "all";
	}
	if(!yearS) {
		var yearS = "all";
	}

	// Initialize countries array
	var ownersPerVisitedCountry = new Array();

	// Walk through years i
	$.each(data.years,function(y,year) {

		// If a year is given, only use data for this year. Else use all years
		if ( y == yearS || yearS == 'all' ) {

			// Walk through the available months
			$.each(year, function(m,month)  {

				// If a month is given, only use data for this month. Else use all months
				if ( m == monthS || monthS == 'all' ) {

					var visitors = new Array();
					var visitorsPerVisitedCountry = new Object();;

					// Walk through the available photos
					$.each(month, function(p,photo)  {				

						// When the owner is unknown / not seen before
						if ( jQuery.inArray(photo.photo_owner, visitors) == -1 ) {

							// Add the owner
							visitors.push(photo.photo_owner);
							
							// When the country does not exist yet
							if ( visitorsPerVisitedCountry[photo.photo_countryid]==undefined ) {
								visitorsPerVisitedCountry[photo.photo_countryid] = 1;
							}
							// When the country already exists
							else {
								visitorsPerVisitedCountry[photo.photo_countryid]++;
							}
						}
					});
					// Sort the array on the number of unique visitors
					if(sortedCountries[y]==undefined){
						sortedCountries[y] = new Object();
					}
					sortedCountries[y][m] = sortCountriesByVisitors(visitorsPerVisitedCountry);			
				}
			});
		}
	});

	return sortedCountries;
}


/**
* Retrieves an array with countries visiting a given country & the number of their unique visitors
* 
*/
function ownersPerSelectedCountry(data, monthS, yearS, countryId) {

	var sortedCountries = new Object();	

	if(!monthS) {
		var monthS = "all";
	}
	if(!yearS) {
		var yearS = "all";
	}

	// Initialize countries array
	var ownersPerCountry = new Array();
	// Keep track of the number of photos
	var photoTotal = 0;
	
	// Walk through years i
	$.each(data.years,function(y,year) {

		// If a year is given, only use data for this year. Else use all years
		if ( y == yearS || yearS == 'all' ) {

			// Walk through the available months
			$.each(year, function(m,month)  {

				// If a month is given, only use data for this month. Else use all months
				if ( m == monthS || monthS == 'all' ) {

					var visitors = new Array();
					var visitorsPerCountry = new Object();;

					// Walk through the available photos
					$.each(month, function(p,photo)  {				

						// If country is the country that's selected by the user
						if ( photo.photo_countryid == countryId ) {

							// When the owner is unknown / not seen before
							if ( jQuery.inArray(photo.photo_owner, visitors) == -1 ) {

								// Raise photo counter
								photoTotal++;
								// Add the owner
								visitors.push(photo.photo_owner);

								// When the country does not exist yet
								if ( visitorsPerCountry[photo.photo_ownercountryid]==undefined ) {
									visitorsPerCountry[photo.photo_ownercountryid] = 1;
								}
								// When the country already exists
								else {
									visitorsPerCountry[photo.photo_ownercountryid]++;
								}
							}
						}
					});
					// Sort the array on the number of unique visitors
					if(sortedCountries[y]==undefined){
						sortedCountries[y] = new Object();
					}
					sortedCountries[y][m] = sortCountriesByVisitors(visitorsPerCountry);			
				}
			});
		}
	});
	
	return sortedCountries;
}

/**
* Retrieve information on a selected country on the map, when a "country-in" is selected
* 
*/
function infoFromSelectedCountry(data, monthS, yearS, countryId, selectedId) {

	var info = new Object();	
	var visitorsTotal = 0;
	var photosTotal = 0;

	if(!monthS) {
		var monthS = "all";
	}
	if(!yearS) {
		var yearS = "all";
	}

	// Walk through years i
	$.each(data.years,function(y,year) {

		// If a year is given, only use data for this year. Else use all years
		if ( y == yearS || yearS == 'all' ) {

			// Walk through the available months
			$.each(year, function(m,month)  {

				// If a month is given, only use data for this month. Else use all months
				if ( m == monthS || monthS == 'all' ) {

					var visitors = new Array();
					
					// Walk through the available photos
					$.each(month, function(p,photo)  {				

						// If country is the country that's selected by the user as "country in"
						if ( photo.photo_countryid == countryId ) {

							if ( photo.photo_ownercountryid == selectedId ) {

								// Raise photo counter
								photosTotal++;

								// When the owner is unknown / not seen before
								if ( jQuery.inArray(photo.photo_owner, visitors) == -1 ) {
	
									// Raise visitor counter
									visitorsTotal++;
									// Add the owner
									visitors.push(photo.photo_owner);
								}
							}
						}
					});
				}
			});
		}
	});
	info['visitors'] = visitorsTotal;
	info['photos'] =  photosTotal;

	return info;
}


/**
* Sorts an array with countries by the number of unique visitors
* 
*/
function sortCountriesByVisitors(visitorsPerCountry) {
	
	// Sorted array to return
 	var sortedCountries = new Object();
	// Stores the maximum number of visitors
	var tempMax = new Array();
	// Stores the number of countries that need to be sorted
	var counter = 0;
	// Count the number of countries that need to be sorted
	for (var count in visitorsPerCountry) {
		counter++;
	}

	// As long as there are countries to sort	
	while (counter > 0)  {

		// Walk through the countries to find the one with the largest number of unique visitors
		for (var country in visitorsPerCountry) {
		
			// When there is no tempMax defined, fill it
			if ( tempMax[0] == undefined ) {
				tempMax[0] = country;
				tempMax[1] = visitorsPerCountry[country];
			}
			// When there is already a tempMax, compare it
			else {
				// When tempMax number of visitors is lower that the one in current itteration, update tempMax
				if ( tempMax[1] <= visitorsPerCountry[country]) {
					tempMax[0] = country;
					tempMax[1] = visitorsPerCountry[country];
				}
			}
		}

		// Store highest remaining visitor number with corresponding country
		sortedCountries[tempMax[0]] = tempMax[1];
		// Remove original information to prevent duplicates / loops
		delete visitorsPerCountry[tempMax[0]];
		// Clean up tempMax, new round
		tempMax = new Array();
		// Lower the remaining countries counter
		counter--;
	}

	return sortedCountries;
}


/**
* Add a new polygon to the map, including events
* 
*/
function addNewPolygon(polygon) {
	// Add the country as an overlay to the map
	map.addOverlay(polygons[polygon]);
	polygons[polygon].hide();
	
	// Add onClick event handler to countries on which more information is available
	// Should be changed to all when a larger dataset is available	
	GEvent.addListener(polygons[polygon],"click", function(polygon, point) {
		return function () {
			if ( jQuery.inArray(polygon, clickablePolygons) != -1 ) {

				if ( polygons[polygon].state == 'selected' ) {
					polygons[polygon].state = '';
					date = $("#monthsList li.active").attr("id").split("-");				
					updateMap(photoData, date[1], date[0]);
					hideMapOverlay();
				}
				else {
					polygons[polygon].state = 'selected';
					date = $("#monthsList li.active").attr("id").split("-");				
					updateMapOnSelect(photoData, date[1], date[0], polygon);
					showMapOverlay();
				}
			}
			else {
				displayMessage('Oh noooes!', 'There\'s no information available, it\'s just a demo (TM)');
			}
		}
	}(polygon));

	GEvent.addListener(polygons[polygon], "visibilitychanged", function(isVisible) {
		if (!isVisible) {
		}
		else {
			polygonVisible();
		}
	});

	polygons[polygon].show();
	//Get Next
	var nextComing = false;
	var nextPolygon;
	for (poly in polygons) {

		if (nextComing == true) {
			nextPolygon = poly;
			currentComing = false;
			break;
		}
		if ( poly == polygon ) {
			nextComing = true;
		}
	}

	if ( nextPolygon != undefined) {
		setTimeout(function() {
				addNewPolygon(nextPolygon);			
		}, 200);
	}
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SUPPORTING FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Toggle the loadingscreen on/off when loading countries from XML
* 
*/
function toggleMainPreloader(){
	if ( !$('#main_preloader').is('*') ) {
		$('body').append('<div id="main_preloader"></div>');
		$('#main_preloader')
		.css('opacity','1.0')
		.css('position','fixed')
		.css('color','#000')
		.css('background','#000000 url(img/ajax-loader3.gif)no-repeat 50% 50%')
		.css('z-index','2000')
		.css('height','100%')
		.css('width','100%')
		.css('top','0')
		.css('left','0');
	}
	else {
		$('#main_preloader').fadeOut(1400);
	}
}

/**
* Determine the number of visible countries and close loadingscreen when all visible
* 
*/
function polygonVisible() {
	visiblePolygons++;
	if (availablePolygons == visiblePolygons) {
		setTimeout("toggleMainPreloader()", 4000);
	}
}

/**
* Display the message bar & message at the top of the screen
* 
*/
function displayMessage(prefix, message){
	if (prefix != '') {
		$('#message').html('<p><strong>'+prefix+' </strong>'+message+' <a id="message_button" href="#" title="Close">[x] close</a></p>');
	}
	else {
		$('#message').html('<p>'+message+' <a id="message_button" href="#" title="Close">[x] close</a>');
	}	
	$('#message').slideDown('normal');
	$('#message_button').click(function(){
		closeMessage();
	});
}

/**
* Hide/close the message bar & message at the top of the screen
* 
*/
function closeMessage(){
	$('#message').fadeOut('slow');
}

/**
* Activates accordion functionality on map overlay
* 
*/
function activateAccordion() {	
	$("#country_information").accordion( {active:0, change: function(accordionchange, ui) { 
		ui.newHeader.addClass('active'); 
		ui.oldHeader.removeClass('active'); 
	}});
}

/**
* Show map overlay
* 
*/
function showMapOverlay() {
	$("#map_overlay").animate({marginLeft: 0}, 1000 );
}

/**
* Hide map overlay
* 
*/
function hideMapOverlay() {
	$("#map_overlay").animate({marginLeft: -260}, 1000 );
}

/**
* Highlight the country that's selected by the user in the FROM field
* 
*/
function showSelected(woeId) {	
	//polygons[woeId].color = cNormal;
	//polygons[woeId].setStrokeStyle({ color: cOutlineSelected });
	//polygons[woeId].state = 'selected';
	//polygons[woeId].redraw(true);	
}

/**
* Sets color for a specific country
* 
*/
function showVisitors(woeId, cIndex) {
	if (polygons[woeId]) {
		polygons[woeId].color = cScale[cIndex];
		polygons[woeId].visiting = true;
		polygons[woeId].redraw(true);
		return true;
	}
}

/**
* Reset colouring for all visiting countries
* 
*/
function resetVisitingCountries(){

	for ( var polygon in polygons ) {
		if ( polygons[polygon].visiting == true ) {
			polygons[polygon].color = cNormal;
			polygons[polygon].visiting = false;
			polygons[polygon].redraw(true);
		}
	}
}

/**
* Reset colouring for all selected countries
* 
*/
function resetSelectedCountries(){

	for ( var polygon in polygons ) {
		if ( polygons[polygon].state == 'selected' ) {
			polygons[polygon].color = cNormal;
			polygons[polygon].setStrokeStyle({ color: cOutline });
			polygons[polygon].state = '';
			polygons[polygon].redraw(true);
		}
	}
}

/**
* Reset timeline by removing all thumbnails
* 
*/
function resetThumbnails(){
	$(".thumbholder").remove();
}

/**
* Set the last month as currently active
* 
*/
function setMonth() {	
	$("#monthsList li:last-child").addClass("active");
	$("#monthsList li:last-child").css("border","1px solid #fcbd0d");
}

/**
* Activate next and deactivate current month
* 
*/
function setMonthUp() {
	current = $("#monthsList li.active")
	next = current.next();
	next.addClass("active");
	current.removeClass("active");
	turnMonthViewerOn(next);
}

/**
* Activate previous and deactive current month
* 
*/
function setMonthDown() {
	current = $("#monthsList li.active");
	previous = current.prev();
	previous.addClass("active");
	current.removeClass("active");
	turnMonthViewerOn(previous);
}

/**
* Add border to the month that's currently active in the timeline
* 
*/
function turnMonthViewerOn(month) {
	$(month).animate({ 
		border: "1px solid #fcbd0d"
	}, 400 );
}

/**
* Remove border from the month that was previously active in the timeline
* 
*/
function turnMonthViewerOff() {
	$("#monthsList li.active").animate({ 
		border: ""
	}, 400 );
}

/**
* Show or hide overlay on timeline
* 
*/
function toggleOverlay(type) {
	if ( $('#overlay').css('display') == 'none' ) {
		$('#overlay').css('display','block');
	}
	else {
		$('#overlay').css('display','none');	
	} 
	$('#'+type+'_overlay').toggle();
}

/**
* Toggle display mode between Montly & Overall
* 
*/
function toggleTimelineMode() {	
	if ( timelineMode == 'monthly' ) {
		timelineMode = 'overall';
	}
	else {
		timelineMode = 'monthly';
	}
}

/**
* Add marker to map
* 
*/
function addThumbClick(photo) {

	$('#'+photo.photo_guid).click(function(){
		
		//  Remove old marker
		removeMarker();
		
		// Add marker to map
		var point = new GLatLng(photo.photo_latitude, photo.photo_longitude);
		activeMarker = new GMarker(point, {icon:icon});
		map.addOverlay(activeMarker);
		
		geocoder.getLocations(point, function(addresses) {	
			var city = '';
			
			if(addresses.Status.code == 200) {	
				// Get adress information from Google's response
				address = addresses.Placemark[0];
				var adress = address.address;
				var adressParts = adress.split(',');
				// When format is <street> <nr>, <postcode> <city>, <country>
				if ( adressParts.length == 3 ) {
					var cityPart = adressParts[1];
					var cityPartParts = cityPart.split(' ');
					if (cityPartParts.length >= 3 ) {
						var temp ='';
						for (var i=2;  i < cityPartParts.length; i++){
							temp = temp + ' ' + cityPartParts[i];
						}
						city = ' in ' + temp;
					}
					else {
						city = ' in ' + cityPartParts[1];
					}
				}
				// When format is <postcode> <city>, <country>
				else if ( adressParts.length == 2 ) {
					var cityPart = adressParts[0];
					var cityPartParts = cityPart.split(' ');
					city = ' in ' + cityPartParts[1];
				}
			}
			
			var html = '<div id="info_window">';
			html += '<h3>'+photo.photo_title+'</h3>';
			html += '<p>Taken by <a class="photographer" href="http://www.flickr.com/people/' + photo.photo_owner + '">' + photo.photo_ownername + '</a> on ' + photo.photo_datetaken + city +'</p>';
			html += '<h4>Other shots taken by this photographer</h4>';
			html += '<ul>';
			html += '<li><a href="#" title="Enlarge"><img src="http://farm3.static.flickr.com/2406/2509489360_7fd87eefce_s.jpg" alt="Dummy" /></a></li>';
			html += '<li><a href="#" title="Enlarge"><img src="http://farm2.static.flickr.com/1027/819607012_132fa6dc42_s.jpg" alt="Dummy" /></a></li>';
			html += '<li><a href="#" title="Enlarge"><img src="http://farm4.static.flickr.com/3085/2701476111_835254511e_s.jpg" alt="Dummy" /></a></li>';
			html += '</ul></div>';
	
			activeMarker.openInfoWindowHtml(html);
			
		});				
	});
}

/**
* Create a new marker indicating the place where a photo has been taken
* 
*/
function createMarker(point,html) {
	var marker = new GMarker(point);
	GEvent.addListener(marker, "click", function() {
	  marker.openInfoWindowHtml(html);
	});
	
	return marker;
}

/**
* Remove marker from the map
* 
*/
function removeMarker() {
	if ( activeMarker != undefined ) {
		map.removeOverlay(activeMarker);
	}
}

/**
* Update the contents of the map overlay when no "country-in" is selected
* 
*/
function updateCountryInfoForVisited(countryId, visitors, visitingCountries, photos, chartUrl) {

	var html = '';

	// Get country name from id (normally from DB)
	var countryName = $("#country_from").find("option[value='"+countryId+"']").text();

	// Set country name on overlay
	$("#country_description h3").html(countryName);

	// Get currently active month & year
	var date = $("#monthsList li.active").attr("id").split("-");
	var monthYear = monthNames[date[0]-1] + ' ' + date[1];
	var total = ''

	if ( visitors == 1 ) {
		visitors = visitors + ' person';
		total = 'who made a total of ';
	}
	else {
		visitors = visitors + ' people';
		total = 'which made a total of ';
	}
	if ( visitingCountries == 1 ) {
		visitingCountries = visitingCountries + ' country';
	}
	else {
		visitingCountries = visitingCountries + ' countries';
	}
	if ( photos == 1 ) {
		photos = photos + ' photo';
	}
	else {
		photos = photos + ' photos';
	}

	html += 'Visited in ';
	html += '<span>' + monthYear + '</span> by ';
	html += '<span>' + visitors + '</span> from ';
	html += '<span>' + visitingCountries + '</span>, ' + total;
	html += '<span>' + photos + '</span>.';
	
	$('#country_infotext').html(html);
	$('#chart').html('<img id="country_chart" src="" alt="Chart" />');
	// Set the chart
	$("#country_chart").attr({ 
		src: chartUrl,
		title: "Popular hours per day",
		alt: "Popular hours per day"
	});	
}

/**
* Update the contents of the map overlay when a "country-in" is selected
* 
*/
function updateCountryInfoForVisiting(countryInId, countryFromId, visitors, photos, chartUrl) {

	var html = '';
	
	// Get country name from id (normally from DB)
	var countryFromName = $("#country_from").find("option[value='"+countryFromId+"']").text();
	var countryInName = $("#country_in").find("option[value='"+countryInId+"']").text();
	
	// Set country name on overlay
	$("#country_description h3").html(countryFromName);
	
	// Get currently active month & year
	var date = $("#monthsList li.active").attr("id").split("-");
	var monthYear = monthNames[date[0]-1] + ' ' + date[1];
	var stay = '';
	
	if ( visitors == 1 ) {
		visitors = visitors + ' person';
		stay = 'that stay';
	}
	else {
		visitors = visitors + ' people';
		stay = 'their stay';
	}
	
	if ( photos == 1 ) {
		photos = photos + ' photo';
	}
	else {
		photos = photos + ' photos';
	}
	
	html += '<span>' + visitors + ' </span> from ';
	html += '<span>' + countryFromName + '</span> visited ';
	html += '<span>' + countryInName + '</span> in ';
	html += '<span>' + monthYear + '</span> and made ';
	html += '<span>' + photos + ' photos</span> during ';
	html += stay + '.';
	
	$('#country_infotext').html(html);
	$('#chart').html('<img id="country_chart" src="" alt="Chart" />');
	// Set the chart
	$("#country_chart").attr({ 
		src: chartUrl,
		title: "Popular hours per day",
		alt: "Popular hours per day"
	});	
}

/**
* Returns the number of photos made in a given country in a specified month (or overall)
* 
*/
function photosPerSelectedCountry(data, monthS, yearS, countryId) {

	if(!monthS) {
		var monthS = "all";
	}
	if(!yearS) {
		var yearS = "all";
	}

	var photoTotal = 0;

	// Walk through years i
	$.each(data.years,function(y,year) {

		// If a year is given, only use data for this year. Else use all years
		if ( y == yearS || yearS == 'all' ) {
		
			// Walk through the available months
			$.each(year, function(m,month)  {
		
				// If a month is given, only use data for this month. Else use all months
				if ( m == monthS || monthS == 'all' ) {

					// Walk through the available photos
					$.each(month, function(p,photo)  {				
						
						// If country is the country that's selected by the user
						if ( photo.photo_countryid == countryId ) {
							
							//  And if it's a country that can be displayed as visiting
							if ( polygons[photo.photo_ownercountryid] != undefined ) {
								photoTotal++;
							}
						}
					});
				}
			});
		}
	});
	return photoTotal;
}

/**
* Returns an url for the Google Chart based on the number of photos per hour
* 
*/
function photosPerHour(data, monthS, yearS, countryId, countryIn) {

	if(!monthS) {
		var monthS = "all";
	}
	if(!yearS) {
		var yearS = "all";
	}
	if(!countryIn) {
		var countryIn = "none";
	}

	var photosPerHour = new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);

	// Walk through years i
	$.each(data.years,function(y,year) {

		// If a year is given, only use data for this year. Else use all years
		if ( y == yearS || yearS == 'all' ) {

			// Walk through the available months
			$.each(year, function(m,month)  {

				// If a month is given, only use data for this month. Else use all months
				if ( m == monthS || monthS == 'all' ) {

					// Walk through the available photos
					$.each(month, function(p,photo)  {				

						// If country is the country that's selected by the user
						if ( photo.photo_countryid == countryId ) {

							//  And if it's a country that can be displayed as visiting
							if ( polygons[photo.photo_ownercountryid] != undefined ) {
								
								if ( countryIn == 'none' ) {
									var dateParts = photo.photo_datetaken.split(" ");
									var time = dateParts[1]
									var timeParts = time.split(":");
									var hour = timeParts[0];								
	
									photosPerHour[hour]++;
								}
								else {
									
									if ( photo.photo_ownercountryid == countryIn ) {
										var dateParts = photo.photo_datetaken.split(" ");
										var time = dateParts[1]
										var timeParts = time.split(":");
										var hour = timeParts[0];								
	
										photosPerHour[hour]++;
									}
									
								}
								
							}
						}
					});
				}
			});
		}
	});
	
	var chartValues = '';
	
	for (var i=0; i<photosPerHour.length; i++) {
		chartValues = chartValues + ',' + photosPerHour[i];
	}
	
	chartValues = chartValues.substr(1);	
	
	var chartType = 'bvs';
	var chartSize = '230x115';
	var chartBarColor = '5c5a5a';
	var chartBarSize = '5,4,4';
	var chartAxis = 'x,y';
	var chartAxisStyle = '0,333333,6,0,lt,d7d7d700|1,FFFFFF00,0,0,t,FFFFFF00';
	var chartBackground = 'bg,s,65432100';
	var chartLabels = '0:|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23'
	var chartScale = '0,20'
	
	var chartUrl =  'http://chart.apis.google.com/chart?';
		chartUrl += 'cht=' + chartType;
		chartUrl += '&chs=' + chartSize; 
		chartUrl += '&chds=' + chartScale;
		chartUrl += '&chco=' + chartBarColor;
		chartUrl += '&chbh=' + chartBarSize;
		chartUrl += '&chxt=' + chartAxis;
		chartUrl += '&chxs=' + chartAxisStyle;
		chartUrl += '&chf=' + chartBackground;
		chartUrl += '&chxl=' + chartLabels;
		chartUrl += '&chd=t:' + chartValues;
	
	return chartUrl;
}