var MAX_DUMP_DEPTH = 10;

var g3_icon = new GIcon();
g3_icon.image = 'g3icon.png';
g3_icon.iconSize = new GSize(26,33);
g3_icon.shadow = 'g3shadow.png';
g3_icon.shadowSize = new GSize(47, 33);
g3_icon.iconAnchor = new GPoint(13, 33);
g3_icon.infoWindowAnchor = new GPoint(13, 0);
//g3_icon.transparent = 'g3icon_ietrans.png';


// NOTE: GSize(width, height) <-- in pixels!!!

function dumpObj(obj, name, indent, depth) {
	if (depth > MAX_DUMP_DEPTH) {
		return indent + name + ": <Maximum Depth Reached>\n";
	}
	if (typeof obj == "object") {
		var child = null;
		var output = indent + name + "\n";
		indent += "\t";
		for (var item in obj)
		{
			try {
				child = obj[item];
			} catch (e) {
				child = "<Unable to Evaluate>";
			}
			if (typeof child == "object") {
				output += dumpObj(child, item, indent, depth + 1);
			} else {
				output += indent + item + ": " + child + "\n";
			}
		}
		return output;
	} else {
		return obj;
	}
}

function Loc (distance, lat, lng, query, name, phone, website) {
	this.distance = distance;
	this.lat = lat;
	this.lng = lng;
	this.query = query;
	this.name = name;
	this.phone = phone;
	this.website = website;

	this.marker = null;	// GMarker.
}

// Note: nulls are less than anything else but null in this sys.
Loc.prototype.lessThan = function (other) {
	if (this.distance == null) {
		if (other.distance == null) {
			return false;
		}
		return true;
	}
	if (other.distance == null) {
		return false;
	}

	return this.distance < other.distance;
}

Loc.prototype.copy = function(other) {
	this.distance = other.distance;
	this.lat = other.lat;
	this.lng = other.lng;
	this.query = other.query;
	this.name = other.name;
	this.phone = other.phone;
	this.website = other.website;
}

Loc.prototype.addMarker = function() {
	this.marker = new GMarker(new GLatLng(this.lat, this.lng), {title: this.name, icon: new GIcon(copy=g3_icon)});
	GEvent.bind(this.marker, "click", this, function () {
		this.marker.openInfoWindowHtml(this.locationInfo());
	});

	map.addOverlay(this.marker);
}

Loc.prototype.locationInfo = function () {
	var text = this.name + '<br />' + this.query;

	if (this.phone != null && this.phone != '') text += '<br />' + this.phone;
	if (this.website != null && this.website != '') {
		var web = this.website.replace(/^\s*http:\/\//i, ''); // Strip http:// out iff there.
		text += '<br /><a href = "http://' + web + '">' + this.website + '</a>';
	}

	return '<div class = "nodeinfo">' + text + '</div>';
}

function NearestLocations(size) {
	this.info = new Array(size);
	this.length = size;
	for (i = 0 ; i < size ; ++i) {
		this.info[i] = new Loc();
	}
}

// for debugging.
NearestLocations.prototype.info_dump = function () {
	var txt = '';
	for (var i = 0 ; i < this.length ; ++i) {
		txt += "\ninfo[" + i + '] = ' + this.info[i].distance;
	}

	alert(txt);
}

NearestLocations.prototype.clear = function () {
	this.info = new Array(this.length);
	for (i = 0 ; i < this.length ; ++i) {
		this.info[i] = new Loc();
	}
}


NearestLocations.prototype.add = function(node) {
	var tmp = new Loc();

	if (node.distance == null) {
		return false;
	}

	for (i = 0 ; i < this.length ; ++i) {
		if (this.info[i].distance == null) {
			this.info[i].copy(node);

			return;
		}
		else if (node.lessThan(this.info[i])) {
			var tmp2 = new Loc();

			// Back up.
			tmp.copy(this.info[i]);
			// Update.
			this.info[i].copy(node);

			for (j = i + 1 ; j < this.length ; ++j) {
				// Special case
				if (this.info[j].distance == null) {
					this.info[j].copy(tmp);
					break;
				}
				else {	// Bubble up.
					tmp2.copy(this.info[j]);
					this.info[j].copy(tmp);
					tmp.copy(tmp2);
				}

			}
			break;
		}
	}
}

function handleError(data) {
	var messages = document.getElementById('messages');
	output = '';
	switch(data) {
		case G_GEO_BAD_REQUEST:
		case G_GEO_SERVER_ERROR:
			output = "Server error.";
			break;
		case G_GEO_MISSING_QUERY:
		case G_GEO_MISSING_ADDRESS: // Note: synonym for previous.
			output = "Missing address.";
			break;
		case G_GEO_UNKNOWN_ADDRESS:
		case G_GEO_UNAVAILABLE_ADDRESS:
			output = "Could not find address.";
			break;
		case G_GEO_UNKNOWN_DIRECTIONS:
			output = "Cannot find route.";
			break;
		case G_GEO_BAD_KEY:
			output = "Invalid Google Maps API key.";
			break;
		case G_GEO_TOO_MANY_QUERIES:
			output = "We're sorry, but we have exceeded the number of requests to Google Maps.  Please try again later.";
			break;
		default:
			alert("Unknown error with Google Maps.");
	}

	if (output) {
		messages.innerHTML = "<h2>" + output + "</h2>";
	}
}

// -----------------------------------------------------------------------------

// Check data returned from geocoder, find routes.
function newUserLocation (data) {
	// Clear out old messages.
	var messages = document.getElementById('messages');
	messages.innerHTML = '';
	
	if (data['Status']['code'] != G_GEO_SUCCESS) {
		handleError(data['Status']['code']);
		return;
	}

/*
	if (data['Placemark'][1]) {
		output = '';
		for (var i in data['Placemark']) {
			output += (output ? ' or ' : ' Did you mean ') + '<b>' + data['Placemark'][i]['address'] + '</b>';
			if (i > 3) {
				break; // Don't want too many outputs.
			}
		}
		output += '?';
		messages.innerHTML = output;
		return;
	}
	*/

	// We gots some data.  Let's groove this thang.

	map.clearOverlays();

	usrLatLng = new GLatLng(
		data['Placemark'][0]['Point']['coordinates'][1],
		data['Placemark'][0]['Point']['coordinates'][0]
	);


	nearest_locations.clear();
	// Distance needs to be updated for all new locations... plus track ze closest.
	for (i in locations) {
		var tmp = new GLatLng(locations[i].lat, locations[i].lng);
		locations[i].distance = usrLatLng.distanceFrom(tmp);
		nearest_locations.add(locations[i]);
	}

	for (i = 0 ; i < nearest_locations.length ; ++i) {
		nearest_locations.info[i].addMarker();
	}

	// Now zoom in.
	var bounds = new GLatLngBounds(usrLatLng, usrLatLng);
	for (i = 0 ; i < 4 ; ++i) {
		bounds.extend(new GLatLng(nearest_locations.info[i].lat, nearest_locations.info[i].lng));
	}
	map.setZoom(map.getBoundsZoomLevel(bounds));
	map.setCenter(bounds.getCenter());
}

function findUserAddress () {
	var country = document.getElementById('country')['value'];
	var city = document.getElementById('city')['value'];
	var prov = document.getElementById('prov')['value'];
	var postal = document.getElementById('postal')['value'];

	var address = '';

	if (city) address += city;
	if (prov) address += (address ? ', ' : '') + prov;
	if (country) address += (address ? ', ' : '') + country;
	if (postal) address += (address ? ' ' : '') + postal;

	geocoder.getLocations(address, newUserLocation);
}

