
var map = null;
var mgr = null;
var icons = [];
var default_chart = 'e';

var info_window_height = 300;

var clicked_marker = null;

var move_listener = null;

var palette_1 = 'nt=000000&rt=ffffff&b1=ffff14&b2=d6d600&b3=999900&b4=009900&b5=009999&b6=000099&b7=0000d6&b8=990099&b9=990000&b10=994d00&t1=T&t2=T&t3=T&t4=R&t5=R&t6=R&t7=R&t8=R&t9=R&t10=R';
var palette_2 = 'nt=ffffff&rt=000000&b1=37ba0c&b2=8aaa1c&b3=76794d&b4=69a599&b5=4284cc&b6=8934ad&b7=b3322f&b8=ff6600&b9=ff9900&b10=82939b&t1=T&t2=T&t3=T&t4=T&t5=T&t6=T&t7=T&t8=T&t9=R&t10=R';

$(document).ready(function() {

	$('head').append('<link type="text/css" rel="stylesheet" media="all" href="' + api_host + '/admissions-gmaps/libs/date-picker/css/datepicker.css" />');
	$('head').append('<link type="text/css" rel="stylesheet" media="all" href="' + api_host + '/admissions-gmaps/infowindow.css" />');

	loadIcons();
	styleElements();
	if (!initAdmissionsMap()) return;

        $('#submit-dates').click(submitDates);

        var date = new Date();

        // Default to year-to-date data
        getData(date.getFullYear() + '-01-01',
                date.getFullYear() + '-' + (parseInt(date.getMonth()) + 1) + '-' + date.getDate());


	datePickerController.create(document.getElementById("start-input"));
	datePickerController.create(document.getElementById("end-input"));

});


function styleElements() {

	$('#date_label').css('float', 'right');
	$('.glyphs').css('clear', 'both');
	$('.glyphs').css('float', 'right');
	$('.glyph').css('float', 'left');
	$('.glyph .label').css('text-align', 'center');

}


function initAdmissionsMap() {

        if (GBrowserIsCompatible()) {

                map = new GMap2(document.getElementById("map_canvas"));
                map.setCenter(new GLatLng(39.815825, -86.154099), 10);
                GEvent.addListener(map, 'click', onMapClicked);
                GEvent.addListener(map, 'dragstart', onMapDragStarted);
				
                mgr = new MarkerManager(map);

                // Navigation
                map.enableScrollWheelZoom();
                map.enableContinuousZoom();
                map.addControl(new GLargeMapControl());

        } else {

		alert('Sorry, your browser is not compatible with Google Maps');
		return false;

	}

	return true;

}

/**
 * Unload the Google map when the window unloads
 */
$(window).unload(function(){
   GUnload();
});


/**
 * Load the icons to be used in the map
 */
function loadIcons() {

	var baseIcon = new GIcon();
	baseIcon.shadow = '';
	baseIcon.iconSize = new GSize(32, 36);
	baseIcon.iconAnchor = new GPoint(16, 36);
	baseIcon.infoWindowAnchor = new GPoint(16, 30);
 
 	for (i=1;i<=8;i++) {
 
 		var img_src = api_host + '/admissions-gmaps/markers/outline-' + i + '.png';
 
		icons[i] = new GIcon(baseIcon);
		icons[i].image = img_src;

		$('#legend .glyphs').append('<div class="glyph" id="glyph-' + i + '"><img src="' + img_src + '"/><div class="label"></div></div>');
		
	}
	
}


/**
 * Request data for the date range specified in the date fields
 */
function submitDates() {
	
	var start_date = $('#start-input').val();
	
	if (!start_date.match(/^\d{4}-\d{2}-\d{2}$/)) {
		alert('Invalid start date: ' + start_date);
		return;
	}
	
	var end_date = $('#end-input').val();
	if (!end_date.match(/^\d{4}-\d{2}-\d{2}$/)) {
		alert('Invalid end date: ' + end_date);
		return;
	}	
	
	if (start_date > end_date) {
		alert('End date cannot precede start date');
		return;
	}

	mgr.clearMarkers();

	// Start a spinner?
	
	getData(start_date, end_date);

}


/**
 * Acquire the data for the given date range
 */
function getData(start_date, end_date) {

	var args = {};
	if (start_date) args.start_date = start_date;
	if (end_date) args.end_date = end_date;

	$('#status').text('Status: acquiring data...');

	$.ajax({
		type: 'GET',
		url: api_host + "/admissions-gmaps/zip_filter.php",
		cache: false,
		data: args,
		dataType: 'jsonp',
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			alert('Unable to acquire data! Try again in a few seconds.');
		},
		success: function(data, textStatus) {
			if (data) {
				gotData(data);
			} else {
				alert('No data retrieved!');
			}
		},
		timeout: 10000
	});

}


/**
 * Format the content for the info window
 */
function formatInfoContent(zip, zipdata) {

	var content = '<div class="info-window" zip="' + zip + '">';

	// Header data
	content += '<div class="zip">' + zip + '</div>';
	content += '<div class="city">' + zipdata['city'] + ', ' + zipdata['state'] + '</div>';
	content += '<div class="count">' + zipdata['count'] + ' admissions</div>';

	// Chart region
	content += '<div class="chart"></div>';
	
	// Chart menu
	content += '<div class="menu"></div>';

	content += '</div>';
	return content;

}


/**
 * Compose the zip skinny embed string for a given chart and zipcode
 */
function formatZipSkinny(zip, chart) { 

	var chart_args = '';
	chart_args += 'e=' + ((chart == 'e') ? 'Y' : 'N') + '&';
	chart_args += 'm=' + ((chart == 'm') ? 'Y' : 'N') + '&';
	chart_args += 'i=' + ((chart == 'i') ? 'Y' : 'N') + '&';
	chart_args += 'o=' + ((chart == 'o') ? 'Y' : 'N') + '&';
	chart_args += 'r=' + ((chart == 'r') ? 'Y' : 'N') + '&';
	chart_args += 'a=' + ((chart == 'a') ? 'Y' : 'N');

	var palette = palette_2;

	return '<iframe src="http://zipwidget.net/widget.php?z=' + zip + '&s=4&p=ffffff&' + palette + '&' + chart_args + '" height="154" width="152" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"><a href="http://zipskinny.com/index.php?zip=' + zip + '" target="_blank">Market Research and Demographic Information for ZIP Code ' + zip + '</a></iframe>';

}


/**
 * Handle the opening of an info window. There is only ever one info window in the DOM.
 */
function onInfoWindowOpened() {

	var zip = $('.info-window').attr('zip');

	// Chart links
	var content = '';
	content += '<a href="#e" class="menu-item">Education</a>';
	content += '<a href="#i" class="menu-item">Income</a>';
	content += '<a href="#a" class="menu-item">Age</a>';
	content += '<a href="#m" class="menu-item">Marriage</a>';
	content += '<a href="#o" class="menu-item">Occupation</a>';
	content += '<a href="#r" class="menu-item">Ethnicity</a>';

	$('.info-window .menu').append(content);

	// Determine the current chart type	
	var chart_type = window.location.hash.substr(1);
	if (!chart_type) chart_type = default_chart; 

	// Load the proper chart and select the corresponding menu item		
	$('.info-window div.chart').append(formatZipSkinny(zip, chart_type));
	$('.info-window a.menu-item[href$=#' + chart_type + ']').addClass('selected');

	// Assign click handlers for the menu items
	$('.info-window a.menu-item').click(function() {

		$('.info-window .menu .selected').removeClass('selected');
		$(this).addClass('selected');

		// Load zip skinny content
		var chart = formatZipSkinny(zip, 
		                            this.href.split('#').pop());

		$('.info-window div.chart').empty();
		$('.info-window div.chart').append(chart);

	});
	
}


/**
 * Create new markers and legend info when data is received
 */ 
function gotData(data) {

	$('#status').text('Status: adding map markers...');

	// Update the date range display
	$('#date_label').empty();
	$('#date_label').append('Admissions for <b>' + data['start_date'] + '</b> through <b>' + data['end_date'] + '</b>');

	$('#start-input').val(data['start_date']);
	$('#end-input').val(data['end_date']);

	var k = Math.log(data['max']);

	// Create the new markers
	var markers = [];
	for (var zip in data['zips']) {
	
		zipdata = data['zips'][zip];
		
		var glyph = Math.min(8, 1 + parseInt(Math.log(zipdata['count'])/(k/8)));
		
		var title_txt = zip + ': ' + zipdata['city'] + ', ' + zipdata['state'] + ': ' + zipdata['count']
		
		var m = new GMarker(new GLatLng(zipdata['lat'], zipdata['lon']),
		                    { icon: icons[glyph],
		                      title: title_txt }); 

		m.bindInfoWindowHtml(formatInfoContent(zip, zipdata), 
		                     { maxWidth: 300 });

		GEvent.addListener(m, "infowindowopen", onInfoWindowOpened); 
		GEvent.addListener(m, "infowindowopen", addMapMoveEndListener);		
		GEvent.addListener(m, "infowindowclose", onInfoWindowClosed);

		markers.push(m);

	}

	/*
	var city_markers = [];
	for (var city in data['cities']) {
	
		var city_data = data['cities'][city];
		
		var glyph = Math.min(8, 1 + parseInt(Math.log(city_data['total'])/(k/8)));
		
		var title_txt = city + ': ' + city_data['total']
		
		var m = new GMarker(new GLatLng(city_data['lat'], city_data['lon']),
		                    { icon: icons[glyph],
		                      title: title_txt }); 

		city_markers.push(m);

	}
	*/

	var state_markers = [];
	for (var state in data['states']) {
	
		var state_data = data['states'][state];

		if (!state_data['total']) continue;
		
		var glyph = Math.min(8, 1 + parseInt(Math.log(state_data['total'])/(k/8)));
		
		var title_txt = state_data['name'] + ': ' +  state_data['total'];
		
		var m = new GMarker(new GLatLng(state_data['lat'], state_data['lon']),
		                    { icon: icons[glyph],
		                      title: title_txt }); 
	
		var rank_content = '<b>Top 5 from ' + state_data['name'] + '</b><br/>';
		rank_content += '<table><tr><th>Zip code</th><th>City</th><th>Admission</th></tr>';
		var odd = true; 
		for (var rank in state_data['ranks']) {
			rank_content += '<tr class="' + (odd ? 'odd' : 'even') + '"><td>'; 
			rank_content += state_data['ranks'][rank]['code'] + '</td><td>';
			rank_content += state_data['ranks'][rank]['city'] + '</td><td align="center">';
			rank_content += state_data['ranks'][rank]['count'] + '</td></tr>';
			odd = !odd;
		}
		rank_content += '</table>';
	
		m.bindInfoWindowHtml(rank_content, { maxWidth: 300 });

		//GEvent.addListener(m, "infowindowopen", infoWindowOpened);
		GEvent.addListener(m, "infowindowopen", addMapMoveEndListener);		
		GEvent.addListener(m, "infowindowclose", onInfoWindowClosed);

		state_markers.push(m);

	}
	
	$('#top_zips tr.data').remove();
	var odd = 1;
	for (var zip in data['ranked']) {
		var zip_data = data['ranked'][zip];
		$('#top_zips').append('<tr class="data ' + (odd ? 'odd' : 'even') + '"><td>' +
		                      zip_data['code'] + '</td><td>' + 
		                      zip_data['city'] + '</td><td>' + zip_data['state'] + '</td><td>' +
		                      zip_data['count'] + '</td></tr>');
		odd = !odd;
	}
	
	//alert(state_markers.length);
	
	// Add the new markers
	mgr.addMarkers(markers, 9);
	//mgr.addMarkers(city_markers, 9, 11);
	mgr.addMarkers(state_markers, 2, 8);
	mgr.refresh();

	// Update the legend glyphs
	for (i=1;i<=8;i++) {
	
		// Determine the number corresponding to this glyph
		var k = Math.log(data['max']);
		var n = parseInt(Math.exp((i-1)*k/8))+1;

		// Add or update the numeral		
		var label = $('#glyph-' + i + ' .label');
		label.text(n);
	}
	
	$('#status').text('Status: done');	

}


/**
 * Add a listener that will respond when map motion ends
 */
function addMapMoveEndListener() {

	move_listener = GEvent.addListener(map, 'moveend', onMapMoveEnd);

}


/**
 * This handler is added after an info window has opened. It performs an extra pan
 * if the info window is not entirely within the map view.
 */
function onMapMoveEnd() {

	var pos = map.fromLatLngToContainerPixel(clicked_marker.getLatLng());
		
	if (pos.y < info_window_height) {
		map.panBy(new GSize(0, info_window_height - pos.y));	
	}

}


/**
 * When the info window is closed, remove any move listener
 */
function onInfoWindowClosed() {

	if (move_listener) {
		GEvent.removeListener(move_listener);
	}

}


/**
 * If the user starts dragging the map, remove any move listener
 */
function onMapDragStarted() {

	if (move_listener) {
		GEvent.removeListener(move_listener);
	}

}


function onMapClicked(overlay, latlng, overlay_latlng) {

	if (overlay instanceof GMarker) {
		clicked_marker = overlay;
	}

}

