var site_url = 'http://' + document.domain + '/map';
var site_image_path = '/images';

var r;
var address_marker;
var markers = [];
var polylines = [];
var selected_storms = [];
var storm_names = [];
var storm_coords = [];
var via_permalink = '';
var default_zoom = 4;
var atlantic_init  = new GLatLng(30.0,-80.0);
var e_pacific_init = new GLatLng(25.0,-120.0);
var w_pacific_init = new GLatLng(27.0,145.0);

var regions = {
	"atlantic"  : "Atlantic Ocean", 
	"w_pacific" : "Western Pacific Ocean", 
	"e_pacific" : "Eastern Pacific Ocean"
};

Event.observe(window, 'load', init, false);
Event.observe(window, 'unload', GUnload, false);

// -------------------------------------------------------------
function init() {
	prevent_frameset();
}

// updates permalink querystring & adds permalink DOM node
// -------------------------------------------------------------
function updatePermalink() {
	var sb = $('sidebar');
	var ni = $('nav-inner');
	var region_uri = {"atlantic": "/atlantic", "w_pacific": "/pacific/west", "e_pacific": "/pacific/east"};
	var url = site_url + region_uri[r] + '/';
	var permalink_url;
	var z = (map.getZoom()!=default_zoom ? '&z='+map.getZoom() : '');
	var ll = '&ll=' + map.getCenter().y + ',' + map.getCenter().x;
	if (!$('storm-permalink')) {
		var a = document.createElement('a');
		var t = document.createTextNode('Link to this map');
		a.setAttribute('id', 'storm-permalink');
		a.setAttribute('title', 'Permanent link to this map');
		a.appendChild(t);
		if (sb) sb.insertBefore(a, ni);
		else sb.appendChild(a);
	}
	permalink_url = (selected_storms.length > 0 ? url + '?' + selected_storms.join('&') + z + ll : url);
	$('storm-permalink').setAttribute('href', permalink_url);
}

// deletes active storm & permalink DOM node; clears querystring
// -------------------------------------------------------------
function resetPermalink() {
	selected_storms = [];
	markers = [];
	polylines = [];
	updatePermalink();
	updateCurrentList();
}

// clears & resets 'selected' attribute for storm year list
// -------------------------------------------------------------
function resetSelected(year) {
	var sy = $('stormyear');
	var sc = sy.getElementsByTagName('option');
	y = (year != null ? year : sy.value);
	var oid = 'y' + y;
	// remove old 'selected' attribute
	for (var i = 0; i < sc.length; i++)
		sc[i].removeAttribute("selected");
	// insert new 'selected' attribute
	if ($(oid)) $(oid).setAttribute("selected", "selected");
}

// removes old selected attr from stormyear menu & adds current
// -------------------------------------------------------------
function optionSelectYear(y){
	var sy = $('stormyear');
	var sc = sy.getElementsByTagName('option');
	var oid = 'y' + y;
	// remove old 'selected' attribute
	for (var i = 0; i < sc.length; i++)
		sc[i].removeAttribute("selected");
	// insert new 'selected' attribute
	$(oid).setAttribute("selected", "selected");
}

// swaps display of active storm list - shows list of all storms
// -------------------------------------------------------------
function showStormlistAll() {
	Element.removeClassName($('nav-inner-crnt'), 'active');
	Element.addClassName($('nav-inner-all'), 'active');
	toggleDisplay('stormlist-all', true);
	toggleDisplay('stormlist-crnt', false);
}

// swaps display of active storm list - shows current map storms
// -------------------------------------------------------------
function showStormlistCurrent() {
	Element.removeClassName($('nav-inner-all'), 'active');
	Element.addClassName($('nav-inner-crnt'), 'active');
	toggleDisplay('stormlist-all', false);
	toggleDisplay('stormlist-crnt', true);
}

// Updates list of displayed storms w/ selected storms
// -------------------------------------------------------------
function updateStormListDisplay() {
	if (!via_permalink) {
		var title_storms = [];
		for (var i = 0; i < selected_storms.length; i++) {
			title_storms.push(storm_names[selected_storms[i]]);
		}
		$('map-description').innerHTML = (title_storms.length > 0 ? '<p>' + title_storms.join(', ') + '</p>' : '');
	}
}

// manages & updates <ul> of currently selected storms
// -------------------------------------------------------------
function updateCurrentList() {
	var sl = $('stormlist-crnt');
	if (selected_storms.length > 0) {
		if (sl!=null) sl.innerHTML = '';
	} else if (selected_storms.length == 0) {
		sl.innerHTML = '<li id="stormlist-default"><em>No storms selected</em></li>';
	}
	for (var i = 0; i < selected_storms.length; i++) {
		var name = storm_names[selected_storms[i]].replace(/(tropical\ storm|tropical\ depression|super\ ?typhoon|hurricane)/i, '');
		var li = document.createElement('li');
		li.id = 's' + selected_storms[i] + '_current';
		li.innerHTML = '<a href="javascript:;" title="Center map on this storm" onclick="map.panTo(new GLatLng('+ storm_coords[selected_storms[i]][0] + ',' + storm_coords[selected_storms[i]][1] + '));return false;">' + name + '</a> <span class="links"><a href="javascript:;" class="del" onclick="deleteStorm(\'' + selected_storms[i] + '\');return false;" title="Remove ' + name + ' from map"></a></span>';
		if (sl!=null) sl.appendChild(li);	
	}
}

// removes markers, polylines, & storm id from active arrays
// -------------------------------------------------------------
function deleteStorm() {
	var storm_ids = '';	// initialize storm id list
	if (arguments.length > 1) fade_single = false;
	else fade_single = true;
	for (var i = 0; i < arguments.length; i++) {
		var index = selected_storms.getIndex(arguments[i]);
		if (index != -1) {
			if ($('s' + arguments[i])) {
				// red fade & loading gif
				Element.removeClassName($('s' + arguments[i]), 'loading-sm');
				if (fade_single) Fat.fade_element('s' + arguments[i], 60, 1000, '#F93636', '');
			}
			delete selected_storms[index];
		}
		if (markers[arguments[i]]) {
			for (var ix = 0; ix < markers[arguments[i]].length; ix++) {
				map.removeOverlay(markers[arguments[i]][ix]);
			}
			delete markers[arguments[i]];
		}
		if (polylines[arguments[i]]) {
			map.removeOverlay(polylines[arguments[i]]);
			delete polylines[arguments[i]];
		}
	}
	// red fade for 'remove all'
	if (!fade_single && selected_storms.length > 0) Fat.fade_element('s' + y + 'sall', 60, 1000, '#F93636', '');
	// completely clean null values out of storms array
	selected_storms = cleanArray(selected_storms);
	map.closeInfoWindow();
	updatePermalink();
	updateCurrentList();
}

// calculate (roughly) distance between two lat/lon points
// -------------------------------------------------------------
function distance(lat_a, lng_a, lat_b, lng_b, u) {
	var k = 57.2957795;                            // degrees in 1 radian
	var r = (u=='km' ? 6378.135 : 3963.189);       // radius of Earth (km or mi)
	var a =  Math.sin(lat_a/k) * Math.sin(lat_b/k);
	var b =  Math.cos(lat_a/k) * Math.cos(lat_b/k) * Math.cos((lng_b/k) - (lng_a/k));
	return reduce( r * Math.acos(a+b) );
}

function reduce(x){ return Math.round(x*1000)/1000;}

// resets default center & zoom for current region
// -------------------------------------------------------------
function resetZoom() {
	switch (r) {
	   case 'atlantic' :
	      map.setCenter(atlantic_init, default_zoom);
	      break;
	   case 'w_pacific' :
	      map.setCenter(w_pacific_init, default_zoom);
	      break;
	   case 'e_pacific' :
	      map.setCenter(e_pacific_init, default_zoom);
	      break;
	   default : map.setCenter(atlantic_init, default_zoom);
	}
	updatePermalink();
}

// returns div used for xmlhttp "loading" indicator
// -------------------------------------------------------------
function loading(id,classname) {
	var d = document.createElement('div');
	var i = document.createElement('img');
	var p = document.createElement('p');
	var t = document.createTextNode('Loading...');
	i.setAttribute('src', site_url + site_image_path + '/loading.gif');
	d.setAttribute('id', id);
	d.className = classname;
	p.appendChild(i);
	p.appendChild(t);
	d.appendChild(p);
	return d;
}

// Sajax-dependent functions
// -------------------------------------------------------------

	function set_region(region,year) {
		r = region;
		y = year;
		var d = loading('stormyear-loading', 'loading');
		var ni = $('nav-inner');
		var sb = $('sidebar');
		Element.addClassName($('nav-' + r), 'current');
		if (ni) sb.removeChild(ni);
		if ($('stormyear') != null) sb.removeChild($('stormyear'));
		if ($('storm-permalink') != null) sb.removeChild($('storm-permalink'));
		if ($('stormlist') != null) {
			sb.removeChild($('stormlist'));
			sb.removeChild($('stormlist-links'));
		}
		// show loading symbol until finished
		if (!$('stormyear-loading')) sb.appendChild(d);
		x_set_region(r,year,set_region_cb);
	}

	function set_region_cb(z) {
		var sb = $('sidebar');
		// remove 'Loading...'
		sb.removeChild($('stormyear-loading'));
		// append year menu
		sb.innerHTML = z;
		resetSelected(y);
		updatePermalink();
		// display current stormlist for permalinks
		if (selected_storms.length > 0)
			via_permalink = true;
		get_stormlist(y);
	}

	function get_stormlist(year) {
		var sb = $('sidebar');
		var sy = $('stormyear');
		var sc = sy.getElementsByTagName('option');
		var y = (year!='' ? year : sy.value);
		var oid = 'y' + y;
		var ni = $('nav-inner');
		if (ni) sb.removeChild(ni);
		var d = loading('stormlist-loading', 'loading');
		// remove old stormlist
		if ($('stormlist') != null) {
			sb.removeChild($('stormlist'));
			sb.removeChild($('stormlist-links'));
		}
		// show loading symbol until finished
		if (!$('stormlist-loading'))
			sb.appendChild(d);
		resetSelected();
		x_get_stormlist(y,r,via_permalink,get_stormlist_cb);
	}

	function get_stormlist_cb(z) {
		var sb = $('sidebar');
		// remove 'Loading...'
		sb.removeChild($('stormlist-loading'));
		// append stormlist to sidebar
		sb.innerHTML = sb.innerHTML + z;
		updateCurrentList();
		updatePermalink();
//		via_permalink = '';
	}

	function get_storm() {
		var storm_ids = '';	// initialize storm id list
		if (arguments.length > 1) fade_single = false;
		else fade_single = true;
		for (var i = 0; i < arguments.length; i++) {
			var sl = $('s' + arguments[i]);
			if (selected_storms.getIndex(arguments[i]) == -1) {
				if (sl) Element.addClassName(sl, 'loading-sm');
				selected_storms.push(arguments[i]);
			}
			storm_ids += arguments[i] + (i != arguments.length-1 ? ',' : '');
		}
		x_get_storm(storm_ids,get_storm_cb);
	}

	function get_storm_cb(z) {
		var s = JSON.parse(z);
		for (var i = 0; i < s.length; i++) {
			createMarkers(s[i]);
			if (s.length == 1) map.panTo(new GLatLng(storm_coords[s[i][0].year + 's' + s[i][0].sid][0], storm_coords[s[i][0].year + 's' + s[i][0].sid][1]));
		}
		if (!fade_single && !via_permalink) Fat.fade_element('s' + y + 'sall', 60, 1000, '#FFFF9C', '#FFFFFF');
		via_permalink = '';
		updateCurrentList();
		updatePermalink();
		updateStormListDisplay();
	}

	function get_address() {
		var a = $('address');
		Element.addClassName(a, 'loading');
		x_get_address(a.value,get_address_cb);
	}
	
	function get_address_cb(z) {
		var s = JSON.parse(z);
		var e = $('address-error');
		var a = $('address');
		Element.removeClassName(a, 'loading');
		e.innerHTML = '';
		// zoom for precision
		var zoom = {
			'address'  : 16,
			'street'   : 15,
			'zip+4'    : 14,
			'zip+2'    : 14,
			'zip'      : 14,
			'city'     : 10,
			'state'    : 6,
			'country'  : 5
		};
		if (!s.error) {
			var lat   = s[0].latitude;
			var lng   = s[0].longitude;
			var addr  = (s[0].address ? s[0].address + ', ' : '' );
			var city  = (s[0].city ? s[0].city + ', ' : '');
			var state = (s[0].state ? s[0].state.toUpperCase() + ', ' : '');
			var zip   = (s[0].zip ? s[0].zip + ', ' : '');
			var cntry = (s[0].country ? s[0].country.toUpperCase() : '');
			var point = new GLatLng(lat,lng);
			if (address_marker!=null) map.removeOverlay(address_marker);
			address_marker = new GMarker(point);
			map.addOverlay(address_marker);
			map.setCenter(point);
			map.setZoom(zoom[s[0].precision]);
			// add tooltip to marker
			address_marker.tooltip = '<p>' + addr + city + state + zip + cntry + '</p>';
			GEvent.addListener(address_marker,"mouseover", function() {
				showTooltip(address_marker);
			});        
			GEvent.addListener(address_marker,"mouseout", function() {
				tooltip.style.visibility="hidden";
			});
			updatePermalink();
		} else {
			e.innerHTML = 'Not Found';
		}
	}

// simple hide/show toggling script
// -------------------------------------------------------------
function toggleDisplay(obj_id,vis) {
	var obj = $(obj_id);
	if (obj) {
		if (vis != null) {
			var state = (vis ? 'block' : 'none');
		} else {
			if (obj.style.display == '' || obj.style.display == 'none'){
				var state = 'block';
			} else {
				var state = 'none';
			}
		}
		obj.style.display = state;
	}
}

// clear & replace function for textfields
function fieldText(f,a) {
	switch (a) {
		case 'clear':
			if (f.defaultValue == f.value) { f.value = ''; }
			break;
		case 'replace':
			if (f.value == '') { f.value = f.defaultValue; }
			break;
	}
} 

// indexOf() for array object
// -------------------------------------------------------------
Array.prototype.getIndex = function(val) {
	for(var i = 0; i < this.length; i++) {
		if(this[i] == val) return i;
	}
	return -1;
}

// returns new array without null/undefined indexes (kludgey)
// -------------------------------------------------------------
function cleanArray(a) {
	var a_new = [];
	for (var i = 0; i < a.length; i++) {
		if (a[i] != null)
			a_new.push(a[i]);
	}
	return a_new;
}

// returns numeric minimum or maximum value from an array
// ----------------------------------------------------------
function minmax(a,t) {
	a.sort(compareNumbers);
	switch(t) {
		case 'min':
			return a[0];
			break;
		case 'max':
			return a[a.length-1];
			break;
		default:
			return null;
	}
}

// for sorting of arrays as integers
// ----------------------------------------------------------
function compareNumbers(a,b) {
   return a - b;
}

// Prevent hotlinking
// ----------------------------------------------------------
function prevent_frameset() {
    if (self != top)
        window.open(site_url, "_top", "");
}
