var map;
var config;
var start;

// saved state of currently selected location
// we keep the forecast and weather cached so
// that we can avoid hitting the remote server too often
var state;

var icons = new Array();
var markers = new Array();

function getQueryElement(what)
{
	var query = window.location.search.substring(1);
	var pairs = query.split("&");
	var where = null;
	
	for (i = 0; i < pairs.length; i++) {
		var pair = pairs[i].split("=");
		if (pair[0] == what) {
			where = decodeURIComponent(pair[1]);
		}
	} 

	return where;
}

function clear_map()
{
	// kill the tide and current graphs
	document.getElementById("tide_txt").style.display = 'none';
	document.getElementById("tide_img").style.display = "none";
	document.getElementById("current_txt").style.display = 'none';
	document.getElementById("current_img").style.display = "none";
	
	// kill the tide and current tables
	document.getElementById("tide_list").innerHTML = "";
	document.getElementById("current_list").innerHTML = "";    
	
	// kill the marine forecast
	document.getElementById("forecast").style.display = "none";
	
	// FIXME - clear all current site data including waather and tide stuff
	// kill the details pane text
}

function redraw_markers(what, show)
{
	for (i = 0; i < markers.length; i++) {
		if (markers[i].location.type == what) {
			if (show)
				map.addOverlay(markers[i]);
			else
				map.removeOverlay(markers[i]);
		}
	}
}

function is_changed(what, show)
{
	var changed = false;
	
	if (what == 'tide') {
	    changed = (show != config.show_tide);
		config.show_tide = show ? 1 : 0;
	} else if (what == 'current') {
	    changed = (show != config.show_current);
		config.show_current = show ? 1 : 0;
	} else if (what == 'launch') {
	    changed = (show != config.show_launch);
		config.show_launch = show ? 1 : 0;
	} else if (what == 'destination') {
	    changed = (show != config.show_destination);
		config.show_destination = show ? 1 : 0;
	} else if (what == 'meeting') {
	    changed = (show != config.show_meeting);
		config.show_meeting = show ? 1 : 0;
	} else if (what == 'sponsor') {
		changed = (show != config.show_sponsor);
		config.show_sponsor = show ? 1 : 0;
	}

	return changed;
}

function refresh()
{
	var types = ['tide', 'current', 'launch', 'destination', 'meeting', 'sponsor'];
	var changed;

	// take any icon changes into account
	for (var i = 0; i < types.length; i++) {
		var type = types[i];
		var show = document.getElementById(type + "_check").checked ? 1 : 0;
		if (is_changed(type, show)) {
			redraw_markers(type, show);
		}
	}

	var redraw = false;
	var days = document.getElementById('days').value;
	
	if (days != config.days) {
		config.days = days;
		redraw = true;
	}
	
	if (!document.getElementById('today').checked) {
		start = document.getElementById('start_date').value;
		
		if (start != '') {
			redraw = true;
		}
	}

//	clear_map();  

	// go and get data for settings
	if (redraw && state.marker)
		fetch(state.marker, false);
}

// centet and zoom the map
function position_map()
{
	// don't know why this is necessary, but the zoom is wacky if I don't force it to a #
	var zoom = config.zoom * 1;
	var center = new GLatLng(config.lat, config.lng);
	map.setCenter(center, zoom);
}

function search()
{
	var search_text = document.getElementById("search_text").value.toLowerCase();
	var results = "<h3>Search Results</h3>\n";
	var found = false;
	
	for (i = 0; i < markers.length; i++) {
		name = markers[i].location.title.toLowerCase();
	
		if (name.match(search_text)) {
			results += "<a href='javascript:void(0)' onClick='fetch(" + i + ", true);'>";
			results += markers[i].location.title;
			results += "</a><br />\n";
			found = true;
		}
	}
	if (!found)
		results += "No matches found<br/>\n";
	document.getElementById("search_results").innerHTML = results;
}

function showtab(id) 
{
	document.getElementById("help_tab").className      = (id == "help") ? "active" : "";
	document.getElementById("weather_tab").className   = (id == "weather") ? "active" : "";
	document.getElementById("info_tab").className      = (id == "info") ? "active" : "";
	document.getElementById("tide_tab").className      = (id == "tide") ? "active" : "";    
	document.getElementById("configure_tab").className = (id == "configure") ? "active" : "";
	document.getElementById("search_tab").className    = (id == "search") ? "active" : "";
	
	document.getElementById("help").style.display = (id == "help") ? "" : "none";
	document.getElementById("weather").style.display = (id == "weather") ? "" : "none";
	document.getElementById("info").style.display = (id == "info") ? "" : "none";
	document.getElementById("tide").style.display = (id == "tide") ? "" : "none";    
	document.getElementById("configure").style.display = (id == "configure") ? "" : "none";    
	document.getElementById("search").style.display = (id == "search") ? "" : "none";        
}

// async function to fetch the marine forecast and inject it into the page
updateForecast = function(text) 
{
	var lines = text.split("\n");
	
	// make sure we're looking at a valid forecast file
	if (lines.length == 0 || !lines[0].match("Marine Forecast ")) {
		document.getElementById("forecast").innerHTML = 
			"<strong>ERROR: unable to retrieve the marine forecast at this time. Try again later.</strong>";
	
		// clear current zone id
		state.zone = "";
	
		// make sure we display the error message
		document.getElementById("forecast").style.display = '';
		return;
	}
	
	// inject the zone forecast into the page
	if (lines[1]) {
		document.getElementById("forecast").innerHTML = "<h3>Marine Forecast</h3>" + lines[1];
		document.getElementById("forecast").style.display = '';
	}
}

function changeBodyClass(from, to) 
{
	document.body.className = document.body.className.replace(from, to);
	return false;
}

function update_tide(type, what, flood, ebb)
{
	var img = type + '_img';
	var txt = type + '_txt';
	var list = type + "_list";
	var flow;
	
	if (what) {
		if (type == 'current') {
			flow = "&nbsp;&nbsp;&nbsp;(flood: " + flood + "&deg; ebb: " + ebb + "&deg;)";
			front = "Currents at ";
		} else {
			front = "Tides at ";
			flow = "";
		}
	
		// try to size the images to the size of the map
		// FIXME: this doesn't work quite correctly - make it smarter
		var mapwidth = map.getSize().width - 24;	
		mapwidth = 950;
	
		var where = encodeURIComponent(what);
	
		// make the station name a little friendlier by chopping ", Washington..." from it
		var shortname = what.substr(0, what.lastIndexOf(',')); 
	
		var addr = "tides.php?mode=graph&" + type + "=" + where + "&width=";
		addr += mapwidth;
		if (start != '')
			addr += '&begin=' + encodeURIComponent(start);
			
		document.getElementById(txt).innerHTML = front + shortname + flow;
		document.getElementById(img).src = addr;
		document.getElementById(txt).style.display = "";
		document.getElementById(img).style.display = "";
	
		var url = "tides.php?days=" + config.days + "&mode=text&" + type + "=" + where;
		if (start != '')
			url += '&begin=' + encodeURIComponent(start);
	
		GDownloadUrl(url, (type == "tide") ? gettide : getcurrent);
	} else {
		document.getElementById(txt).style.display = "none";
		document.getElementById(img).style.display = "none";
		document.getElementById(list).innerHTML = "";
	}
}

function gettable(index, raw)
{
	var location = markers[index].location;
	var lines = raw.split("\n");
	var shortname = location.title.substr(0, location.title.lastIndexOf(','));
	var head = (location.type == "tide") ? "Tides: " : "Currents: ";
	var text ="<h3>" + head + shortname + "</h3>\n"
	
	if (location.type == 'current') {
		text += "Flood:" + location.flood + "&deg;&nbsp;&nbsp;&nbsp;Ebb:" + location.ebb + "&deg;<br/>\n";
	}
	
	text += "<pre>\n";
	
	for (i = 5; i < lines.length; i++)
		text += lines[i] + "\n";
	text += "</pre>\n";
	
	document.getElementById(location.type + "_list").innerHTML = text;
}

gettide = function(raw)
{
	gettable(state.tide, raw);
}

getcurrent = function(raw)
{
	gettable(state.current, raw);
}

function fetch(index, hilite)
{
	var marker    = markers[index];
	var location  = marker.location;
	var shortname;
	var text;
	
	if ((i = location.title.lastIndexOf(',')) >= 0)
		shortname = location.title.substr(0, i);
	else
		shortname = location.title;
	
	document.getElementById('loc').innerHTML = ": " + shortname;
	document.getElementById('tide_list').innerHTML = "";
	document.getElementById('current_list').innerHTML = "";    
	
	// save the index of this location
	state.marker = index;
	
	// center the map on the point
	// FIXME: will need to do this after opening side panel in the future
	map.panTo(location.point);

	if (location.type == "launch")
		text = "Launch Site: ";
	else if (location.type == "meeting")
		text = "Meeting Place: ";
	else if (location.type == "sponsor")
		text = "Sponsor: ";
	else if (location.type == "destination")
		text = "Destination: ";
	else if (location.type == "tide")
		text = "Tide Station: ";
	else if (location.type == 'current')
		text = "Current Station: ";
	document.getElementById("heading").innerHTML = text + shortname + "<br/>";
	
	if (location.type == 'tide' || location.type == 'current') {
		text = '<p>"' + location.title + '" is a ' + location.type + 
			" station. Click the tides tab for more information.</p>";
	} else {   
		text = location.details ? location.details : "";
	}
	document.getElementById('details').innerHTML = text;
	
	if (location.zone) {
		// don't go get it if we already fetched it.
		// small petential for expired data if the page is left open for a long time
		// we can be smarter and check the expire time later on.
		if (state.zone == location.zone) {
			document.getElementById("forecast").style.display = "";
		} else {
			state.zone = location.zone;	
			GDownloadUrl("marine.pl?FORECAST=" + location.zone, updateForecast);
		}
	} else {
		document.getElementById("forecast").style.display = "";
		document.getElementById("forecast").innerHTML = 
			"<p><strong>There is no marine forecast for this location.</strong></p>";
		state.zone = 0;
	}
	
	var tide;
	if (location.type == 'tide') {
		tide = location.title;
		state.tide = index;
	} else if (location.tide_station) {
		for (i = 0; i < markers.length; i++) {
			if (location.tide_station == markers[i].location.tid) {
				tide = markers[i].location.title;
				state.tide = i;
				break;
			}
		}
	}
	update_tide('tide', tide);
	
	var current, ebb, flood;
	if (location.type == 'current') {
		current = location.title;
		ebb = location.ebb;
		flood = location.flood;
		state.current = index;
	} else if (location.current_station) {
		for (i = 0; i < markers.length; i++) {
			if (location.current_station == markers[i].location.cid) {
				state.current = i;
				current = markers[i].location.title;
				ebb = markers[i].location.ebb;
				flood = markers[i].location.flood;
				break;
			}
		}
	}
	update_tide('current', current, flood, ebb);
	
	if (!tide && !current) {
		document.getElementById("tide_list").innerHTML = 
			"<p><strong>There is no tide or current data for this location.</strong></p>";
	}
	
	if (location.city)
	{
		if (state.weather != location.city) {
			var link = "http://www.wunderground.com/US/WA/" + location.city + ".html";
			var img = 
				"http://banners.wunderground.com/weathersticker/bigwx_cond/language/www/US/WA/" + 
				location.city + ".gif";
			document.getElementById("weather_link").href = link;
			document.getElementById("weather_img").src = img;
			state.weather = location.city;
		}
	}

	if (hilite)
		marker.openInfoWindow(location.title);
}

function is_visible(location)
{
	if (location.type == 'tide')
	    return config.show_tide == 1;
	else if (location.type == 'current')
	    return config.show_current == 1;
	else if (location.type == 'launch')
	    return config.show_launch == 1;
	else if (location.type == 'destination')
	    return config.show_destination == 1;		
	else if (location.type == 'meeting')
	    return config.show_meeting == 1;
	else if (location.type == 'sponsor')
	    return config.show_sponsor == 1;		
	return false;
}

function create_station(i, point, location)
{
	var ic;
	ic = get_icon(location.type);
	
	markers[i] = new GMarker(
		point, {icon:ic, title:location.title});
	
	GEvent.addListener(markers[i], "click", 
		function() {
			fetch(i, false);
		}
	);
	
	markers[i].location = location;
	markers[i].lid = i;
	
	if (is_visible(location))
		map.addOverlay(markers[i]); 
}

function load_markers()
{
	GDownloadUrl("datapoints.xml", function(data, responseCode) 
	{
		var xml = GXml.parse(data);
		var stations = xml.documentElement.getElementsByTagName("station");
		
		for (var i = 0; i < stations.length; i++) {
		
			var points = stations[i].getElementsByTagName("marker");
			var flow   = stations[i].getElementsByTagName("flow");
			var point  = new GLatLng(parseFloat(points[0].getAttribute("lat")),
			parseFloat(points[0].getAttribute("lng")));
			
			var location = new Object;
			
			location.id    = i;
			location.point = point;
			location.type  = stations[i].getAttribute("station_type");
			location.title = stations[i].getAttribute("title");
			location.zone  = stations[i].getAttribute("zone");
			location.tid   = stations[i].getAttribute("tid");
			location.cid   = stations[i].getAttribute("cid");
			location.details = stations[i].getElementsByTagName("details")[0];
			location.tide_station = GXml.value(stations[i].getElementsByTagName("tide_station")[0]);
			location.current_station = GXml.value(stations[i].getElementsByTagName("current_station")[0]);
			location.city = GXml.value(stations[i].getElementsByTagName("city")[0]);
			location.details = GXml.value(stations[i].getElementsByTagName("details")[0]);
			
			if (flow[0])
			{
				location.ebb   = flow[0].getAttribute("ebb");
				location.flood = flow[0].getAttribute("flood");
			}
			
			create_station(i, point, location);       
		}
		changeBodyClass('loading', 'standby');
			
		if (config.location) {
		// FIXME - make this cleaner and integrate with the serach function
			if (!config.location.match("^[0-9]+$")) {
				// see if we're in the database
				where = config.location.toLowerCase();
				config.location = null;
				for (i = 0; i < markers.length; i++) {
					name = markers[i].location.title.toLowerCase();
	
					if (name.match(where)) {
						config.location = i;
					}
				}
			}
			if (config.location) {
				fetch(config.location, true);
				showtab("info");
			}
		}
	});
}

function get_icon(type)
{
	for (i = 0; i < icons.length; i++)
	{
		if (icons[i].type == type)
			return icons[i].icon;
	}
	return G_DEFAULT_ICON;
}

// create a small icon
function makeSmallIcon(color)
{
	var icon = new GIcon();
	icon.image = "icons/small-" + color + ".png";
	icon.shadow = "icons/small-shadow.png";
	icon.iconSize = new GSize(12, 20);
	icon.shadowSize = new GSize(22, 20);
	icon.iconAnchor = new GPoint(6, 20);
	icon.infoWindowAnchor = new GPoint(5, 1);
	
	return icon;
}

// create a large icon
function makeLargeIcon(color)
{
	var icon;
	if (color == 'orange')
		icon = G_DEFAULT_ICON;
	else
		icon = new GIcon(G_DEFAULT_ICON, "icons/large-" + color + ".png");
	return icon;
}

function create_icon(type, color)
{
	var data = new Object();
	
	data.type = type
	data.icon = makeSmallIcon(color);
	data.visible = true;
	icons.push(data);
}

function make_icons()
{
	create_icon('tide', 'purple');
	create_icon('current', 'blue');
	create_icon('launch', 'yellow');
	create_icon('destination', 'red');
	create_icon('meeting', 'green');
	create_icon('sponsor', 'orange');
}

function save_config()
{
	var center = map.getCenter();
	var type = map.getCurrentMapType();
	
	if (type == G_NORMAL_MAP)
		config.mode = 'map';
	else if (type == G_SATELLITE_MAP)
		config.mode = 'sat';
	else if (type == G_HYBRID_MAP)
		config.mode = 'hybrid';
	else
		config.mode = G_NORMAL_MAP;
	
	config.lat = center.lat();
	config.lng = center.lng();
	config.zoom = map.getZoom();
	
	if (state.marker) {
		config.location = state.marker;
	}
	config.store();
}

function clear_config()
{
	config.remove();
}

// set up initial map params, get from cookie if we have one
function get_config()
{
	config = new Cookie(document, "mapthing", -1);

	if (!config.load()) {
		config.show_tide = 1;
		config.show_current = 1;
		config.show_launch = 1;
		config.show_destination = 1;
		config.show_sponsor = 1;
		config.show_meeting = 1;
		config.location = "";
		config.lat = 48.74;
		config.lng = -122.479;
		config.zoom = 11;
		config.days = 3;
		config.start = '';
		config.mode = 'map';
	}
	
	var loc = getQueryElement('location');
	if (!loc)
		loc = getQueryElement('name');
	if (loc)
		config.location = loc;
}

function enable_date(enabled)
{
	document.getElementById('start_date').disabled = !enabled;
	document.getElementById('b_cal').disabled = !enabled;
}

function setup_map()
{
	var type;
	
	map = new GMap2(document.getElementById("map"));
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
	map.addControl(new GScaleControl( ));
	position_map();
	
	if (config.mode == 'sat')
		type = G_SATELLITE_MAP;
	else if (config.mode == 'hybrid')
		type = G_HYBRID_MAP;
	else
		type = G_NORMAL_MAP;
	
	map.setMapType(type);
}

function set_customize_form()
{
	document.getElementById("tide_check").checked = config.show_tide == 1 ? true : false;
	document.getElementById("current_check").checked = config.show_current == 1 ? true : false;
	document.getElementById("launch_check").checked = config.show_launch == 1 ? true : false;    
	document.getElementById("destination_check").checked = config.show_destination == 1 ? true : false;
	document.getElementById("meeting_check").checked = config.show_meeting == 1 ? true : false;
	document.getElementById("sponsor_check").checked = config.show_sponsor == 1 ? true : false;
	
	document.getElementById("days").value = config.days;
	document.getElementById("today").checked = true;
	document.getElementById("start_date").value = "";
//	enable_date(false);
}

function init()
{
    if (GBrowserIsCompatible()) {
		make_icons();
		get_config();
		set_customize_form();
		
		state = new Object();
		state.zone = "";
		state.weather = "";
		state.tide = "";
		state.current = "";
		state.marker = '';
	
		setup_map();
	}
     
	load_markers();
}

