        var map = null;             // main map object
        var panorama = null;        // main panorama object
        
        // default map settings
        var x = 145.192317; // longitude
        var y = -38.098712;  // latitude
        var zoom = 12;      // map zoom level
        var mapType = 0;    // 0=road 1=sat 2=hybrid 3=terrain

        // streetview settings
        var pitch = 0;      // 90=Sky 0=Horizon -90=Ground
        var magnify = 0;    // 0=Normal 1=Level 1 Zoom 2=Level 2 Zoom
        var bearing = 0;    // View Direction in  Degrees
        
        var linkShow = false;        // include a link to full screen map and street view
        var coordShow = false;       // show streetview coordinates and direction below the streetview
        var scrollWheelOn = false;  // scrollwheel zooming      
        var mapControlType = 1;     // 0=None 1=Small 2=Large
        var initialView = false;     // false=start in map view, true=start with full window street view

        var streetviewOverlay = false;        
        var streetviewClient = null;        
        var currentMode = -1;       // 0= map 1=street view
        
        // dimensions of browser window
        var windowWidth = 640;
        var windowHeight = 280;        
        var streetTitle = "";       // Area title displayed above Street View panorama        

        var latlng = null;          // current marker location
        var marker = null;          // streetview marker object
        var streetviewValid = false;    // set if a street view exists for current latlng
        var panInitialized = false;     // set when a valid panorama is found druing an update
        
        var tooltip = null;     // the tooltip div
        var dragging = false;   // flag set when map marker is being dragged
        var panLoading = false;     
        var oldLatlong = null;
        var oldStreetTitle = "";
        
        // initial map and street view settings, used for restoreView()
        var origLatlng = null;
        var origZoom = 0;
        var origBearing = 0;
        var origPitch = 0;
        var origMagnify = 0;
        
        // get the control settings contained in the url
        function decodeParameters()
        {
            var queryString = document.location.search.substring(1) + "&";    
            var xParam = getParameter(queryString, "x");
            var yParam = getParameter(queryString, "y");        
            var zoomParam = getParameter(queryString, "z"); 
            var maptypeParam = getParameter(queryString, "t"); 
            var mapcontrolParam = getParameter(queryString, "c"); 

            var bearingParam = getParameter(queryString, "b"); 
            var pitchParam = getParameter(queryString, "p");
            var magnifyParam = getParameter(queryString, "m");

            var coordShowParam = getParameter(queryString, "j");
            var linkShowParam = getParameter(queryString, "k");
            var scrollwheelParam = getParameter(queryString, "s"); 
            var initialviewParam = getParameter(queryString, "v"); 
            
            if (xParam.length)
            {
                x = parseFloat(xParam);
            }       
            if (yParam.length)
            {
                y = parseFloat(yParam);
            }       
            if (zoomParam.length)
            {
                zoom = parseFloat(zoomParam);
            }       
            if (maptypeParam.length)
            {
                mapType = parseFloat(maptypeParam);
            }       
            
            if (mapcontrolParam.length)
            {
                mapControlType  = parseInt(mapcontrolParam);
            }
            
            if (bearingParam.length)
            {
                bearing = parseInt(bearingParam);
            }       
            if (pitchParam.length)
            {
                pitch = parseInt(pitchParam);
            }       
            if (magnifyParam.length)
            {
                magnify = parseInt(magnifyParam);
            }       
            
            if (coordShowParam.length)
            {
                coordShow = (coordShowParam == "1");
            }       
            if (linkShowParam.length)
            {
                linkShow = (linkShowParam == "1");
            }       
            if (scrollwheelParam.length)
            {
                scrollWheelOn = (scrollwheelParam == "1");
            }       
            if (initialviewParam.length)
            {
                initialView = (initialviewParam == "1");
            }       
            
            // default location - should be a location with a street view panorama available
            latlng = new GLatLng(y,x);
            
            // store original view
            origLatlng = latlng;
            origZoom = zoom;
            origBearing = bearing;
            origPitch = pitch;
            origMagnify = magnify;
        }        
        
        // apply the selected street view size
        function setMode(a)
        {
            currentMode = a;

            if (currentMode == 1)   // Maximize - hide map and show the full panorama div
            {
                initPanorama(latlng);
            }
            else
            {                
                eID("panFrame").style.display = "none";
                eID("mapFrame").style.display = "block";

                resizeMap();
                
                map.setCenter(latlng);
                showTooltip();
            }
        }
        
        // create map with street view enabled and initial location marker
        function initMap()    
        {
            var mapTypeCodes = [G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP, G_PHYSICAL_MAP];
            decodeParameters();

            // get initial window dimensions            
            resizeMap();
            
            map = new GMap2(eID("mapDiv"));
            map.addMapType(G_PHYSICAL_MAP);
            
            if (mapControlType == 1)
            {
                map.addControl(new GSmallMapControl());
            }
            if (mapControlType == 2)
            {
                map.addControl(new GLargeMapControl());
            }
            
            map.addControl(new GScaleControl());
            map.addControl(new GMenuMapTypeControl());
            map.enableDoubleClickZoom();
            map.enableContinuousZoom();
            if (scrollWheelOn)
            {
                map.enableScrollWheelZoom();
            }
            // marker tooltip div
            tooltip = document.createElement("toolDiv");
            map.getPane(G_MAP_FLOAT_PANE).appendChild(tooltip);
            tooltip.style.visibility = "hidden";
            tooltip.innerHTML = "<div id='tooltipText' class='markerTooltip'>&nbsp;</div>";
    
            map.setCenter(latlng,zoom);
            map.setMapType(mapTypeCodes[mapType]);
            
            // set up street view overlay and client
            streetOverlay = new GStreetviewOverlay();
            // map.addOverlay(streetOverlay);
            map.removeOverlay(streetOverlay);
            streetviewClient = new GStreetviewClient();
            
      
            // enable map ads - change id/channel or disable as required
            var showAds =false;
            if (showAds)
            {
                var adsenseID = "ca-pub-5408854154696215";
                var adsenseChannel = "5533804922";
                var adManager = new GAdsManager(map, adsenseID, {channel:adsenseChannel});
                adManager.enable();
            }

            createMarker();
            
            GEvent.addListener(map, "click", function(overlay, point)
            {
                // remember previous point
                oldLatlong = latlng;
                oldStreetTitle = streetTitle;
                
                if (point)
                {
                    pitch = 0;
                    magnify = 0;
                    initPanorama(point);
                }
            });
            
            GEvent.addListener(map, "zoomend", function()
            {
                showTooltip();
            });
            
            if (initialView)
            {
                // start in Street View
                eID("mapFrame").style.display = "none";
                eID("panFrame").style.display = "block";
            }
            
            updatePanStats();
            initPanorama(latlng);
        }
        
        // Create the main panorama
        function createPanorama(container)
        {
            if (panorama == null)
            {
                // create the panorama
                panorama = new GStreetviewPanorama(container);
                panorama.setLocationAndPOV(latlng, {"yaw":bearing,"pitch":pitch,"zoom":magnify});
                
                // listen for changes in bearing and latlng, then update marker accordingly
                GEvent.addListener(panorama,"yawchanged",function(a)
                     {
                        bearing = parseFloat(a);
                        updateMarker();
                        updatePanStats();                
                     });

                GEvent.addListener(panorama,"pitchchanged",function(a)
                     {
                        pitch = parseFloat(a);
                        updatePanStats();                

                     });

                GEvent.addListener(panorama,"zoomchanged",function(a)
                     {
                        magnify = parseInt(a);
                        updatePanStats();                
                     });

                GEvent.addListener(panorama,"initialized",function(a)
                     {
                        latlng = a.latlng;
                        streetTitle = a.description;
                        
                        updateMarker();
                        updatePanStats();
                     }); 
            }
        }

        // Create the Street View map marker
        function createMarker()
        {
            var icon = new GIcon();

            var imageNum = Math.round(bearing/22.5) % 16;
            var imageUrl = "http://maps.google.com/intl/en_us/mapfiles/cb/man_arrow-" + imageNum + ".png";
            
            icon.image = imageUrl;
            icon.iconSize = new GSize(49,52);
            icon.iconAnchor =  new GPoint(25,36);
            
            marker = new GMarker(latlng, {"icon":icon, "draggable":true});
                         
            GEvent.addListener(marker, "dragstart", function()
           {            
                dragging = true;
                hideTooltip();

                // remember original point
                oldLatlong = latlng;
                oldStreetTitle = streetTitle;
           });              
            
            GEvent.addListener(marker, "dragend", function()
           {            
                dragging = false;
                latlng = marker.getPoint();
                
                // reset streetview pitch/zoom but keep current streetview bearing
                magnify = 0;
                pitch = 0;
                initPanorama(latlng); 
           });              
            
           GEvent.addListener(marker, "click", function()
           {  
                hideTooltip();

                // reset streetview pitch/zoom but keep current streetview bearing
                magnify = 0;
                pitch = 0;
                
                panLoading = true;
                initPanorama(latlng);
           }); 
            
            map.addOverlay(marker);
        }

        // Update the co-ordinate and link labels at the base of the control        
        function updatePanStats()
        {
            var panTitle = eID("panTitle");
            if (panTitle)
            {
                panTitle.innerHTML = streetTitle;
            }            
            
            eID("tooltipText").innerHTML = formatTooltip(streetTitle);

            // display current lat long and direction
            if (coordShow)
            {
                var coordLabel = eID("coordLabel");
                var html = "lat <b>" + latlng.lat() + "&deg;</b> lng <b>" + latlng.lng() + "&deg;</b> dir <b>" + parseInt(bearing) + "&deg;</b>";
                if (coordLabel)
                {
                    coordLabel.innerHTML = html;
                }
            }                

            // display links to full page map and street view
            if (linkShow)
            {
                var linkLabel = eID("linkLabel");
                if (linkLabel)
                {
                    var link = "http://data.mapchannels.com/streetmap/v1/streetmap.htm?x=" + 
                        formatFloat(latlng.lng(),6) + "&y=" + formatFloat(latlng.lat(),6) + "&z=" + map.getZoom() +
                        "&b=" + formatFloat(bearing,1) + "&p=" + formatFloat(pitch,1) + "&m=" + magnify + "&s=1";
                    var html = "bookmarks &nbsp;" +
                        "<a target='_blank' href='" + link + "&v=0' style='color:green; font-weight:bold' title='Full Page Map'>Map</a> &nbsp;" +
                        "<a target='_blank' href='" + link + "&v=1' style='color:green; font-weight:bold' title='Full Page Street View'>Street View</a> &nbsp;" +
                        "<a target='_blank' href='http://www.streetcities.com/' style='color:green; font-weight:bold' title='www.streetcities.com - Free Street View and Mapping Tools'>Street Cities</a>";

                    linkLabel.innerHTML = html;
                }                
            }
        }

        function updateMarker()
        {            
            // update marker image
            var imageNum = Math.round(bearing/22.5) % 16;
            var imageUrl = "http://maps.google.com/intl/en_us/mapfiles/cb/man_arrow-" + imageNum + ".png";                
            marker.setImage(imageUrl);
          
           if (!dragging)
           {
                // update marker location
                marker.setPoint(latlng);                
            }
        }
        
        // return to the initial map location
        function viewRestore()
        {
            latlng = origLatlng;
            zoom = origZoom;
            
            bearing = origBearing;
            pitch = origPitch;
            magnify = origMagnify;
            
            map.setCenter(latlng, zoom);
            
            initPanorama(origLatlng);
        }

        // find nearest panorama      
        function initPanorama(point)
        {                
            if (!panInitialized)
            {
                createPanorama(eID("panDiv"));
                panInitialized = true;
            }   
            
            // change current point (note, if a nearby street view is found then the latlng will be updated to the latlng of the streetview)
            streetviewClient.getNearestPanorama(point, initPanorama2);
        }

        // callback function for initPanorama() - change panorama view to specified latlong
        function initPanorama2(param)
        {
            // validate new location
            streetviewValid  = true;
            if ((param == null) || (param.location == null))
            {
                // No Street View available, return to the previous view
                streetviewValid  = false;
                latlng = oldLatlong;
                streetTitle = oldStreetTitle;
                
                // map.setCenter(latlng);
            }
            else
            {    
                // store new streetview location and title
                var location = param.location;
                latlng = location.latlng;
                streetTitle = location.description;                
                if (oldStreetTitle == "")
                {
                    oldStreetTitle = streetTitle;
                }
            }
                
            updateMarker();            
            updatePanStats();                
            showTooltip();

            if (panLoading && streetviewValid)
            {
                currentMode = 1;
            }            
            panLoading = false;     // reset            
            
            if (currentMode == 1)
            {
                panorama.hide();
                panorama.setLocationAndPOV(latlng, {"yaw":bearing,"pitch":pitch,"zoom":magnify});

                // wait for the panorama to load
                setTimeout("initPanorama3()", 250);
            }
            
        }

        // display the updated panorama
        function initPanorama3()
        {
            eID("mapFrame").style.display = "none";
            eID("panFrame").style.display = "block";
            
            panorama.show();
        }

        // Hide/show the street view overlay
        function streetGridClick(a)
        {
            if (a.checked)
            {
                map.addOverlay(streetOverlay);
            }
            else
            {
                map.removeOverlay(streetOverlay);
            }
        }

        // when the main window is resized resize map and panorama
        function resizeMap()
        {
            if (typeof(window.innerHeight) != "number")
            {
                windowWidth = parseInt(document.documentElement.clientWidth);
                windowHeight = parseInt(document.documentElement.clientHeight);
            }
            else
            {
                windowWidth = parseInt(window.innerWidth);
                windowHeight = parseInt(window.innerHeight);
            }

            var mapDiv = eID("mapDiv");
            var panDiv = eID("panDiv");
            
            if (mapDiv)
            {
                mapDiv.style.width = (windowWidth) + "px";
                mapDiv.style.height = (windowHeight - 50) + "px";
            }
            
            if (panDiv)
            {            
                panDiv.style.width = (windowWidth) + "px";
                panDiv.style.height = (windowHeight - 52) + "px";
            }
            
            if (map)
            {
                map.checkResize();
            }
            
            if (panorama)
            {
                panorama.checkResize();
            }
        }

        // tidy up when closing the page        
        function closeMap()
        {
            if (panorama)
            {
                panorama.remove();
            }
            GUnload();
        }
        
        
        // show marker tooltip on the map adjacent to the marker
        function showTooltip()
        {
            if (!dragging)
            {
                var zoom = map.getZoom();
                
                var l_pt = map.getCurrentMapType().getProjection().fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true), zoom);
                var l_offset = map.getCurrentMapType().getProjection().fromLatLngToPixel(latlng, zoom);
                var l_size = new GSize(l_offset.x - l_pt.x + 16, l_offset.y - l_pt.y);
                var l_pos = new GControlPosition(G_ANCHOR_TOP_LEFT, l_size); 
                
                l_pos.apply(tooltip);
                tooltip.style.visibility = "visible";
            }
	    }

        // hide the marker tooltip
        function hideTooltip()
        {
	        tooltip.style.visibility = "hidden";
        }

        // utils
        function eID(id)
        {
            return document.getElementById(id); 
        }   
            
        function getParameter(q, n)
        {
           var r = "";
           if (q && q.length > 0 && n && n.length)
           {
                var p = n + "=";
                var b = q.indexOf(p);
                if (b != -1)
                {
                    b += p.length;
                    var e = q.indexOf("&" , b);      
                    if (e == -1) e = n.length;
                    r = unescape(q.substring(b,e));
               }
           }    
           return r;
        }
            
        function formatTooltip(a)
        {
            var text = "";
            
            for (var i=0; i<a.length; i++)
            {
                var c = a.substr(i,1);
                if (c == ' ' || c == '+')
                {
                    text += "&nbsp;";
                }
                else
                {
                    text  += c;
                }
            }
            
            return text;
        }
        
        var ffLookup = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 ];
        
        function formatFloat(a, p)
        {
            var m = ffLookup[p];
            return parseInt(a * m) / m;
        }
        window.onload=initMap;
        window.onresize=resizeMap;
        window.onunload=closeMap;
