var map             = null;
var geo             = null;
var bounds          = null;
var addresses       = null;
var __DEBUG         = false;

// USE:
//  canvas:     ID (string) of the element where you wish the map to be placed
//  controls:   true/false (bool) true if you wish to display controls on the map
function initialiseMap(canvas, controls) {
    if (GBrowserIsCompatible()) {
        try {
            // Initialise Google Map API and instantiate a GClientGeocoder class
            map         = (map == null) ? new GMap2(document.getElementById(canvas)) : map;
            geo         = (geo == null) ? new GClientGeocoder() : geo;
            bounds      = (bounds == null) ? new GLatLngBounds() : bounds;
            addresses   = (addresses == null) ? new Array() : addresses;
            
            GEvent.addListener(map, 'load', function() {
		        debug(">>> Google map has finished loading <<<");
	        });
            
            map.setCenter(new GLatLng(-25.601902,133.725586), 8);
            displayMarkers();
            fitAllMarkers();
            
            // Add controls
            if (controls) {
                map.addControl(new GSmallMapControl());
				map.addControl(new GMapTypeControl());
            }
        } catch (ex) {
            debug(ex.description);
        }
    }
}

// Add an address item to the global variable
function addAddress(index, address, html, link) {
    geo         = (geo == null) ? new GClientGeocoder() : geo;
    
    if (address) {
        geo.getLatLng(address, function(point) {
            if (point) {
                // Expand the boundary to include this point
                bounds = (bounds == null) ? new GLatLngBounds() : bounds;
                bounds.extend(point);

                var marker = createMarker(point, index, html, link);
                    
                if (marker) {
                    debug("Adding marker: " + marker);
                    addresses = (addresses == null) ? new Array() : addresses;
                    addresses.push(marker);
                }
            }
        });
    }
}

// Display markers
function displayMarkers() {
    if (addresses.length > 0) {
        var i = 0;
        for (i = 0; i < addresses.length; i++) {
            if (addresses[i]) {
                debug("Adding overlay at address index: " + i);
                var marker = addresses[i];
                map.addOverlay(marker);
            }
        }
    }
}

// Fit all markers on the map by zooming out
function fitAllMarkers() {
    if (map) {
        if (bounds) {
            map.setZoom(map.getBoundsZoomLevel(bounds));
            map.setCenter(bounds.getCenter());
        } else {
            alert("There are no markers or places to process");
        }
    } else {
        alert("Please initialise the map first by running: initialiseMap(canvas[, controls, address])");
    }
}

/***************************************
 *** INTERNAL FUNCTIONS - DO NOT USE ***
 ***************************************/

// Creates a marker whose info window displays the letter corresponding
// to the given index.
function createMarker(point, index, html, link) {
    // Create a base icon for all of our markers that specifies the
    // shadow, icon dimensions, etc.
    var baseIcon = new GIcon(G_DEFAULT_ICON);
    baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
    baseIcon.iconSize = new GSize(20, 34);
    baseIcon.shadowSize = new GSize(37, 34);
    baseIcon.iconAnchor = new GPoint(9, 34);
    baseIcon.infoWindowAnchor = new GPoint(9, 2);

	// Create a lettered icon for this point using our icon class
	var range = "Z".charCodeAt(0) - "A".charCodeAt(0) + 1;
    var letter = String.fromCharCode("A".charCodeAt(0) + (index % range));
	var letteredIcon = new GIcon(baseIcon);
	letteredIcon.image = "http://www.google.com/mapfiles/marker" + letter + ".png";

	// Set up our GMarkerOptions object
	markerOptions = { icon:letteredIcon };
	var marker = new GMarker(point, markerOptions);
    
    // Marker's & Link's click events
    GEvent.addDomListener(document.getElementById(link), "click", function() {
        if (html)
            marker.openInfoWindowHtml(html);
        else
            marker.openInfoWindowHtml("<strong>" + letter + "</strong>");
            
        map.panTo(marker.getLatLng());
        map.setZoom(15);
    });
    
    GEvent.addListener(marker, "click", function() {
        if (html)
            marker.openInfoWindowHtml(html);
        else
            marker.openInfoWindowHtml("<strong>" + letter + "</strong>");
            
        map.panTo(marker.getLatLng());
        map.setZoom(15);
    });
    
	return marker;
}

function debug(message) {
    if (__DEBUG)
        try {
            console.debug(message);
        } catch (ex) {
            alert(message);
        }
}