function initMaps() {
    /**
     * Resizes the map canvas to 100% height when browser window changes.
     * @param {Event} e
     */
    function resizeWindow(e)
    {
        // this only needs adjusted on the index
        document.getElementById('map_canvas').style.height=document.documentElement.clientHeight-149+'px';
        sidebar.style.height=document.documentElement.clientHeight-149+'px';
        if (map) map.checkResize();
    }
    /**
     * Gets a color that has not been used yet and returns it.
     * @return {String} Hex color code
     */
    function pickColor()
    {
        var color = genHex();
        while (color in used_colors)
        {
            color = genHex();
        }
        used_colors[color] = true;
        return color;
    }
    /**
     * Generates a random hex color
     * @return {String} Hex color code
     */
    function genHex()
    {
        var colors = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
        var digit = new Array(5);
        var color = "";
        for (i=0; i<6; i++)
        {
            digit[i] = colors[Math.round(Math.random()*14)];
            color += digit[i];
        }
        return color;
    }
    function centerMap(lat, lng)
    {
        map.panTo(new google.maps.LatLng(lat, lng));
    }
    /**
     * Creates a new polygon on the current map with an unused color.
     * @param {Array} Array of coordinates
     * @param {Color} Optional color code to draw the shape as.
     * @return {GPolygon}
     */
    function drawShape(coords, color)
    {
        if (!color) var color = pickColor();
        else used_colors[color] = true;
        active_shape = new google.maps.Polygon(coords.concat(coords[0]), '#' + color, 2, .8, '#' + color, .4);
        map.addOverlay(active_shape);
        return active_shape;
    }
    /**
     * Creates a new path on the current map with an unused color.
     * @param {Array} Array of coordinates
     * @param {Color} Optional color code to draw the shape as.
     * @return {GPolyline}
     */
    function drawPath(coords, color)
    {
        if (!color) var color = pickColor();
        else used_colors[color] = true;
        active_shape = new google.maps.Polyline(coords, '#' + color, 2, .8);
        map.addOverlay(active_shape);
        return active_shape;
    }
    function generateShapeInfoHtml(id)
    {
        var map_data = __places__[parseInt(id)];
        if (!map_data) return;
        var html = document.createElement('div');
        html.className = 'infobox';
        var cur = document.createElement('h3');
        cur.innerHTML = map_data.label;
        html.appendChild(cur);
        var cur = document.createElement('h4');
        cur.innerHTML = LOCATION_CATEGORIES[map_data.category];
        html.appendChild(cur);
        var cur = document.createElement('p');
        cur.innerHTML = map_data.description;
        html.appendChild(cur);
        var cur = document.createElement('ul');
        var li = document.createElement('li')
        var a = document.createElement('a');
        a.innerHTML = 'More information about this location';
        a.href = map_data.url;
        a.onclick = function(event){ window.location.href=this.href; return false; }
        li.appendChild(a);
        cur.appendChild(li);
        html.appendChild(cur);
        return html;
    }
    function round(value, length)
    {
        if (!length) var length = 0;
        var round_value = '';
        for (var i=0; i<length; i++)
            round_value += '0';
        round_value = parseInt(round_value)
        return Math.round(value*round_value)/round_value;
    }
    function centerOnShape(id)
    {
        id = parseInt(id);
        var overlay = __placecache__[id];
        var bounds = overlay.getBounds();
        var center = bounds.getCenter();
        map.setZoom(map.getBoundsZoomLevel(bounds));
        map.panTo(center);
        map.openInfoWindow(center, generateShapeInfoHtml(id));
    }
    
    if (google.maps.BrowserIsCompatible()) {
        var sidebar = document.getElementById('sidebar');

        // This has to happen first
        resizeWindow();
        
        var cur = document.getElementById("map_canvas");
        var map = new google.maps.Map2(cur);
        map.setCenter(new google.maps.LatLng(38.88, -102.442626), 4);
        map.addControl(new google.maps.LargeMapControl(), new google.maps.ControlPosition(G_ANCHOR_TOP_LEFT, new GSize(10,40)));
        map.addControl(new GMapTypeControl(), new google.maps.ControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,40)));
        
        // reference containers
        var active_shape = null;
        var used_colors = {};
        
        window.onunload = google.maps.Unload;

        window.onresize = resizeWindow;
        
        var els = document.getElementById('sidebar').getElementsByTagName('a');
        var el;
        for (var i=0; (el=els[i]); i++) {
            var id = parseInt(el.getAttribute('rel'));
            if (id) {
                el.onclick = function(event) {
                    centerOnShape(this.getAttribute('rel'));
                };
            }
        }
        
        GEvent.addListener(map, "click", function(overlay,latlng)
        {
            if (overlay && overlay.getBounds)
            {
                map.openInfoWindow(overlay.getBounds().getCenter(), generateShapeInfoHtml(overlay.id));
                return;
            }
        });
        
        var first;
        for (place in __places__) {
            var place = __places__[place];
            var points = [];
            for (var i=0; i<place.points.length; i++) {
                points.push(new google.maps.LatLng(place.points[i][0], place.points[i][1]));
            }
            if (place.is_path) var shape = drawPath(points, place.color);
            else var shape = drawShape(points, place.color);
            shape.id = place.id;
            if (!first) first = place.id;
            __placecache__[place.id] = shape;
        }
        centerOnShape(first);
    }
}
google.setOnLoadCallback(initMaps);
var __placecache__ = {};