/****************
GLOBAL VARIABLES 
******************/
//Uncategorized global variables 
var map = null;
var lock;
var bounds;	// Keeps track of marker boundary

//Artist information global variables
var artistName = "";
var artistID = 0;
var artistPictureUrl = "";
var alternateArtistsInfo = "";


//Artist event global variables
var numEvents;
var uniqueLocations;
var tourInformation = null;  //entries consist of city name, string information about event if this city is redundant
var tourStops = null;
var tourIndex = null;


/****************
CONSTANTS
******************/
var INITIAL_ZOOM = 1;
var APP_KEY = "cjfNFkLMTQxxCPjz";
var MESSAGE_NO_ARTIST = "Eventful search found no results. Please try another artist name.";
var MESSAGE_NO_EVENTS = "This artist has no upcoming events on Eventful.";
var NUM_ALTERNATE_ARTISTS = 10;
var DEFAULT_ICON_URL = "http://www.google.com/mapfiles/markerA.png";
var START_ICON_URL = "http://www.google.com/mapfiles/dd-start.png";
var END_ICON_URL = "http://www.google.com/mapfiles/dd-end.png";
var BASE_ICON_WIDTH = 24;
var BASE_ICON_HEIGHT = 48;
var TOUR_STOP_ICON_WIDTH = 24;
var TOUR_STOP_ICON_HEIGHT = 24;
var WINDOW_ANCHOR_X = 9;
var WINDOW_ANCHOR_Y = 2;
var ZOOM_LEVEL = 13;




/****************
"PUBLIC" FUNCTIONS
These are the only functions that should be used by external programs
******************/

/*
showMap displays the map corresponding to the input name.

Inputs:
	name - String name of the artist
Outputs:
	-1 - Error
	0 - Successful map display.
*/
function showMap(name) 
{
	artistName = name;
	
	// Lock
	if(lock==null)
	{
		// DEBUG: check lock is null on script's first call.
		//alert("LOCK IS NULL.");
		lock=1;	// Initialize lock
	}
	else if (lock > 0)
	{
		lock = 1;
		
		// DEBUG
		alert("Please wait for search to complete.");
		return -1;
		setTimeout("showMap(name)",5000);
	}
	else
	{
		lock=lock+1;
	}
	
	
	//Return if the browser cannot support GoogleMaps
	if (!GBrowserIsCompatible()) 
	{
		document.writeln("Incompatible browser! <br>");
		return -1;
	}
	
	
	//Initialize a blank map and right-click functionality
	if (map == null)
	{
		map = new GMap2(document.getElementById("map_canvas"));
		map.enableScrollWheelZoom();
		map.addControl(new GLargeMapControl3D());
		map.addControl(new GMapTypeControl(true));
		map.setCenter(new GLatLng(0,0),INITIAL_ZOOM);
		GEvent.addListener(map, "singlerightclick", function() {
			map.openInfoWindowHtml(map.getCenter(), 
				"<b>The Tour Stops of " + artistName + " are currently being displayed.<br><br>" + 
				"Additional artists: </b><br>" + alternateArtistsInfo);
		});
	}
	else map.setCenter(new GLatLng(0,0),INITIAL_ZOOM);
	map.clearOverlays();
	
	
	//Map the artist with the name closest to the input
	var oArgs_performer = {
		app_key: APP_KEY,
		q: name,
		page_size: 1
	};
	EVDB.API.call("/performers/search", oArgs_performer, parsePerformerData);

	
	//Find artists with similar first names and similar last names
	var nameParts = name.split(" ");	
	alternateArtistsInfo = "";
	
	var totalArtistsToFind = (NUM_ALTERNATE_ARTISTS / 2) + 1;
	if (nameParts.length > 1)
	{
		var oArgs_performer_alternate = {
			app_key: APP_KEY,
			q: nameParts[nameParts.length-1],
			page_size: totalArtistsToFind
		};
		EVDB.API.call("/performers/search", oArgs_performer_alternate, buildAlternatePerformerList);
	}
	else totalArtistsToFind = 1+NUM_ALTERNATE_ARTISTS;

	var oArgs_performer_alternate = {
		app_key: APP_KEY,
		q: nameParts[0],
		page_size: totalArtistsToFind
	};
	EVDB.API.call("/performers/search", oArgs_performer_alternate, buildAlternatePerformerList);
}





/****************
"PRIVATE" FUNCTIONS
These functions shouldn't be used by external programs
******************/

/*
Find the names of artists in the input.
These names are added onto a string that contains artists with similar names to the best matching artist.
This string pops up when a user right clicks on the map.

Input:
	artistsData - JSON formatted strings giving information about multiple artists
*/
function buildAlternatePerformerList(artistsData)
{
	//List length is the lower of total artist's found and artists on the first search page
	var numArtists = parseInt(artistsData.total_items);  
	var page_size = parseInt(artistsData.page_size); 
	if(numArtists > artistsData.page_size)
		numArtists = page_size;
	
	//For each artist, give the link to the Eventful webpage & the choice to plot their tour.
	for (var i = 0; i < numArtists; i++)
	{
		var name = artistsData.performers.performer[i].name;
		if (name == artistName)
			continue;
		name = "\'" + name + "\'";
		alternateArtistsInfo += "<b><a href=" + artistsData.performers.performer[i].url + " target=_blank>" + artistsData.performers.performer[i].name +"</a>";
		alternateArtistsInfo += "  -  ";
		alternateArtistsInfo += '<a href="javascript:showMap(' + name + ');"' + '>Map this Artist!</a></b><br>';
	}
}



/*
Parses the Eventful results about the best-matching artist.
Stores the performer's name, Eventful ID, and link to a picture.

Input:
	artistsData - JSON formatted strings giving information about the artist
*/
function parsePerformerData(artistsData)
{
	// If artist not found, notify user with popup
	if (artistsData.performers == null)
	{
		map.openInfoWindow(map.getCenter(),
                document.createTextNode(MESSAGE_NO_ARTIST));
		lock=lock-1;
		return;
	}
	
	//Store the performer's name, Eventful ID, and link to picture.
	artistName = artistsData.performers.performer[0].name;
	artistID = artistsData.performers.performer[0].id;
	if (artistsData.performers.performer[0].image != null  &&  artistsData.performers.performer[0].image.thumb.url != "")
		artistPictureUrl = artistsData.performers.performer[0].image.thumb.url;
	else artistPictureUrl = DEFAULT_ICON_URL; 
	
	
	//Search for events relating to the artist
	var oArgs_event = {
		app_key: APP_KEY,
		id: artistID,
		show_events: "true"	
	};
	EVDB.API.call("/performers/get", oArgs_event, parseEventData);
}




/*
Find all events relating to an artist.
Pass each event's information to a marker creator.

Input:
	eventsData - JSON formatted strings containing information about multiple events
*/
function parseEventData(eventsData)
{
	// Artist has no events
	if (eventsData.events == null)
	{
		map.openInfoWindow(map.getCenter(),
                document.createTextNode(MESSAGE_NO_EVENTS));
		lock=lock-1;
		return;
	}
	
	// Initialize global variables when artist has events
	var events = eventsData.events.event;
	numEvents = events.length;
	uniqueLocations = numEvents;
	tourStops = new Array(numEvents);
	tourInformation = new Array(numEvents);
	tourIndex = 0;
	
	// Initialize boundary for this artist
	bounds = new GLatLngBounds();
	
	
	//Grab each tour stop's city name, time, and url
	for (var i = 0; i < numEvents; i++)
	{
		var dateTimeArray = events[i].start_time.split(" ");
		var yearMonthDateArray = dateTimeArray[0].split("-");

		var hourMinuteSecondArray = dateTimeArray[1].split(":");
		var startHour = parseInt(hourMinuteSecondArray[0]);
		var timeStr = "";	
		var time_meridian = "AM";
		
		if (startHour == 0)
		{
			timeStr = "Not listed.";
		}
		else if (startHour >= 12)
		{
			time_meridian = "PM";
			if (startHour > 13)
				startHour -= 12;
			timeStr = startHour + ":" + hourMinuteSecondArray[1] + " " + time_meridian;
		}

		var cityName, cityString;
		if (events[i].location == null)
			cityName = "Not listed";
		else cityName = events[i].location;
		cityString = "<b>" +
			"Date: " + yearMonthDateArray[1] + "-" + yearMonthDateArray[2] + "-" + yearMonthDateArray[0] + "<br>" +
			"Time: " + timeStr + "<br>" +
			"Location:  " + cityName + "<br>" +
			'<a href="'+events[i].url+'" target=_blank>More Info - Eventful.com</a><br>' +
			"</b>";
		
		tourInformation[i] = new Array( cityName, cityString );
	}


	//Only place markers for non redundant cities
	for(var i = 0; i < numEvents; i++)
	{
		var plotMarker = true;
		for (var j = 0; j < i && plotMarker; j++)
		{
			if (events[i].location == tourInformation[j][0])
				plotMarker = false;
		}
		if (!plotMarker)
		{
			uniqueLocations--;
			continue;
		}
			
		var oArgs = {
			app_key: APP_KEY,
			id: events[i].id
		};
		EVDB.API.call("/events/get", oArgs, placeMarker);
		
		// Lock: only need to decrement due to timeout in main function
		if(lock > 1)
		{
			lock=lock-1;
		}
	}  
}


/*
Grab the location, date, and time about a particular event.
Put this information in a marker and place the marker on the map.

Input:
	eventData - JSON formatted strings about a specific event
*/
function placeMarker(eventData)
{
	// Lock
	if(lock > 1)
	{
		// Only return because we're returning into the recursive for loop where placeMarker was called
		return -1;
	}
	

	var lat = eventData.latitude;
	var lng = eventData.longitude;

    var baseIcon =  new GIcon(G_DEFAULT_ICON);
    baseIcon.iconSize = new GSize(BASE_ICON_WIDTH, BASE_ICON_HEIGHT);
	baseIcon.iconAnchor = new GPoint(BASE_ICON_WIDTH/2, BASE_ICON_HEIGHT);
	baseIcon.infoWindowAnchor = new GPoint(WINDOW_ANCHOR_X, WINDOW_ANCHOR_Y);
    
    // Add marker location to boundary
    bounds.extend(new GLatLng(lat,lng));

	tourStops[tourIndex] = new GLatLng(lat,lng);
	tourIndex++;
	if (tourIndex == 1)
	{
		//Add the starting icon
		var startIcon = baseIcon;
		startIcon.image = START_ICON_URL;
		startMarkerOptions = {icon:startIcon};
		var startMarker = new GMarker(new GLatLng(lat,lng), startMarkerOptions); 
		GEvent.addListener(startMarker, "click", function() {
			startMarker.openInfoWindowHtml("<b>Tour starts here!</b>");
		});
		map.addOverlay(startMarker);
		
		// Special case of only 1 event
		if (tourIndex==numEvents)
		{
			// Lock - decrement after plotting last point
			lock=lock-1;
			
			// Resize map to fit all markers 
			map.setZoom(map.getBoundsZoomLevel(bounds));
			map.setCenter(bounds.getCenter());
		}
	}
	else if (tourIndex == uniqueLocations)
	{
		//Add the ending icon
		var endIcon = baseIcon;
		endIcon.image = END_ICON_URL;
		endMarkerOptions = {icon:endIcon};
		var endMarker = new GMarker(new GLatLng(lat,lng), endMarkerOptions); 
		GEvent.addListener(endMarker, "click", function() {
			endMarker.openInfoWindowHtml("<b>Tour ends here!</b>");
		});
		map.addOverlay(endMarker);
		
		//Trace the tour route
		var polyline = new GPolyline(tourStops, "#ff0000", 3);
		map.addOverlay(polyline);
		
		// Lock - decrement after plotting last point
		lock=lock-1;
		
		// Resize map to fit all markers 
		map.setZoom(map.getBoundsZoomLevel(bounds));
		map.setCenter(bounds.getCenter());
	}
	
	//Add the tour stop marker
	var tourStopIcon = new GIcon(G_DEFAULT_ICON);
    tourStopIcon.iconSize = new GSize(TOUR_STOP_ICON_WIDTH, TOUR_STOP_ICON_HEIGHT);
    tourStopIcon.iconAnchor = new GPoint(TOUR_STOP_ICON_WIDTH/2, TOUR_STOP_ICON_HEIGHT);
    tourStopIcon.infoWindowAnchor = new GPoint(WINDOW_ANCHOR_X, WINDOW_ANCHOR_Y);
	tourStopIcon.image = artistPictureUrl;
    markerOptions = {icon:tourStopIcon};
    var marker = new GMarker(new GLatLng(lat,lng), markerOptions);   
	
	//Create the text that will go with the marker
	var redundantCityString = "";
	for (var i = 0; i < numEvents; i++)
	{
		if ( (tourInformation[i][0] == eventData.city)  ||  
			 (tourInformation[i][0] == (eventData.city + ", " + eventData.region_abbr)) )
			redundantCityString += (tourInformation[i][1] + "<br>");
	}
	if (redundantCityString == "" )  //An internal Eventful database bug occurred so re-calculate everything
	{								//This differs from the very similar code above so I did not make another function
		var dateTimeArray = eventData.start_time.split(" ");
		var yearMonthDateArray = dateTimeArray[0].split("-");

		var hourMinuteSecondArray = dateTimeArray[1].split(":");
		var startHour = parseInt(hourMinuteSecondArray[0]);
		var timeStr = "";	
		var time_meridian = "AM";
		
		if (startHour == 0)
		{
			timeStr = "Not listed.";
		}
		else if (startHour >= 12)
		{
			time_meridian = "PM";
			if (startHour > 13)
				startHour -= 12;
			timeStr = startHour + ":" + hourMinuteSecondArray[1] + " " + time_meridian;
		}

		var loc = "";
		if (eventData.city != null)
			loc += eventData.city;
		if (eventData.city == null && eventData.country != null)
			loc += (eventData.country);
		else if (eventData.country != null)
			loc += (", " + eventData.country);
		else
			loc += "Not listed.";
		redundantCityString += "<b>" +
			"Date: " + yearMonthDateArray[1] + "-" + yearMonthDateArray[2] + "-" + yearMonthDateArray[0] + "<br>" +
			"Time: " + timeStr + "<br>" +
			"Location:  " + loc + "<br>" +
			'<a href="'+eventData.url+'" target=_blank>More Info - Eventful.com</a><br><br>' +
			"</b>";
	}
	
    GEvent.addListener(marker, "click", function() {
		var lat = marker.getLatLng().lat(), lng=marker.getLatLng().lng(); 
		marker.openInfoWindowHtml(
		"<b>" + 
		redundantCityString + 
		'<a href="javascript:map.setCenter(new GLatLng(' + lat + ', ' + lng + '), ' + ZOOM_LEVEL +');">Zoom Here</a></b>');
	});
	map.addOverlay(marker);
}
