GOOGLEMAPS  = function () {

    //global map object
    GOOGLEMAPS.prototype.map = null;
    GOOGLEMAPS.prototype.counter = 0;

    //default map settings
    GOOGLEMAPS.prototype.currentLat = 37;
    GOOGLEMAPS.prototype.currentLng = -122;
    GOOGLEMAPS.prototype.currentZoom = 4;
    GOOGLEMAPS.prototype.mapElement = "googlemap";
    GOOGLEMAPS.prototype.plugin = null;
    GOOGLEMAPS.prototype.autoCenter = true;

    //data
    GOOGLEMAPS.prototype.markers = new Array;
    GOOGLEMAPS.prototype.polies = new Array;
    GOOGLEMAPS.prototype.overlay = null;
    GOOGLEMAPS.prototype.bounds = new google.maps.LatLngBounds();


    //try to load and show map
    GOOGLEMAPS.prototype.initMap = function() {
        if(this.map != null) return;

        //check if map object has been loaded or created
        try{
            document.getElementById(this.mapElement).innerHTML;
        }catch(e){
            if (this.counter > 60) {
                alert('Can\'t load map! Can\'t find map object!');
            } else {
                setTimeout("gmaps.initMap()", 1000);
                this.counter++;
            }
            return false;
        }

        //If gmaps main.js didn't load try to call init again after 60 tries we give up
        if (typeof google.maps != "object") {
            if (this.counter > 60) {
                document.getElementById(this.mapElement).innerHTML = 'Can\'t load map! Gmap server timeout! ';
            } else {
                setTimeout("gmaps.initMap()", 1000);
            }
            this.counter++;
            return false;
        }

        //map center
        var startPos = new google.maps.LatLng(this.currentLat, this.currentLng);

        //setup map
        this.map = new google.maps.Map(document.getElementById(this.mapElement), {
            zoom: this.currentZoom,
            center: startPos,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            mapTypeControl: true,
            streetViewControl:true
        });

        //add zoomend event
        google.maps.event.addListener(this.map, 'zoom_changed', function() {
            try{
                document.getElementById('infoLabel').style.display='none';
            }catch(e){}
        });

        //add overlays
        this.overlay = new MAPOVERLAY();
        this.overlay.setMap(this.map);
        this.addPolies();

        //calculate bounds
        for(i in gmaps.markers){
            marker = gmaps.markers[i];
            if(marker.LatLng == null){
                marker.LatLng = new google.maps.LatLng(marker.lat, marker.lng);
                this.bounds.extend(marker.LatLng);
            }
        }

        if(this.autoCenter) this.map.fitBounds(this.bounds);

    }

    GOOGLEMAPS.prototype.zoomToMarker = function(idx) {
        var latLng = new google.maps.LatLng(gmaps.markers[idx].lat,gmaps.markers[idx].lng);
        gmaps.map.setCenter(latLng);
        gmaps.map.setZoom(12);
    }

    GOOGLEMAPS.prototype.addPolies = function() {
         for(i in gmaps.polies){
            poly = gmaps.polies[i];
            path = google.maps.geometry.encoding.decodePath(poly.path);

            for(ii in path){
                gmaps.bounds.extend(path[ii]);
            }

            var polyOptions = {
                strokeColor: poly.color,
                strokeOpacity: poly.opacity,
                strokeWeight: poly.weight,
                path:path
            }
            poly = new google.maps.Polyline(polyOptions);
            poly.setMap(this.map);
        }
    }

}


MAPOVERLAY  = function (){}

    MAPOVERLAY.prototype = new google.maps.OverlayView();
    MAPOVERLAY.prototype.layer = null;
    MAPOVERLAY.prototype.overlayProjection = null;
    MAPOVERLAY.prototype.infowindow = new google.maps.InfoWindow();

    //add new layer to map pane when adding this ovelay
    MAPOVERLAY.prototype.onAdd = function() {
      this.layer = document.createElement('DIV');
      this.getPanes().floatPane.appendChild(this.layer);
    }

    //this event is fired on init and zoom change
    MAPOVERLAY.prototype.draw = function() {

        var html = '';

        //add each markers to map
        for(i in gmaps.markers){
                marker = gmaps.markers[i];

                //calculate marker postions
                this.overlayProjection = this.getProjection();
                if(marker.LatLng == null){
                    marker.LatLng = new google.maps.LatLng(marker.lat, marker.lng);
                    gmaps.bounds.extend(marker.LatLng);
                }
                var pos = this.overlayProjection.fromLatLngToDivPixel(marker.LatLng);

                if(marker.icon.length<2) marker.icon = gmaps.plugin + 'imgs/m.png';

                //build marker html
                html += '<a onmouseover="gmaps.overlay.showLabel(this,' + i + ')" onmouseout="gmaps.overlay.hideLabel()" ';
                if(marker.href != undefined ) html += ' href="' + marker.href + '"';
                //else html += ' href="#" onclick="gmaps.zoomToMarker(' + i + ')" ';
                if(marker.infowindow.length>2) html += ' href="javascript:gmaps.overlay.showInfo('+i+')" ';
                html += ' style="background:none;line-height:0;z-index:'+(i)+';position:absolute;left:' + (pos.x-marker.mw) + 'px;top:' + (pos.y-marker.mh) + 'px"><img src="' + marker.icon + '"></a>';



        }

        //insert markers to map pane
        this.layer.innerHTML = html;


    }

    MAPOVERLAY.prototype.showInfo = function (idx){
        gmaps.overlay.infowindow.content = '<div class="infowindow">' + gmaps.markers[idx].infowindow.replace(/&gt;/gi,">").replace(/&lt;/gi,"<").replace(/&amp;/gi,'&').replace(/&quot;/gi,'"') + '</div>';
        gmaps.overlay.infowindow.setPosition(new google.maps.LatLng(gmaps.markers[idx].lat, gmaps.markers[idx].lng));
        gmaps.overlay.infowindow.open(gmaps.map);
    }


    MAPOVERLAY.prototype.hideLabel = function (){
        document.getElementById('infoLabel').style.display='none';
    }

    //caculate label postion and show
    MAPOVERLAY.prototype.showLabel = function (m,idx){


            //try to get label element if not in the body add it
            try{
                document.getElementById('infoLabel').innerHTML;
                var label = document.getElementById('infoLabel');
            }catch(e){
                var label = document.createElement('div');
                label.setAttribute('id','infoLabel');
                label.style.position = "absolute";
                label.onclick = function(){marker.hidePointLabelElement()}
                document.body.appendChild(label);
            }

            if(gmaps.markers[idx].hover.length<1) return false;

            //calculate absolute postion of the label
            var map = this.findPos(document.getElementById(gmaps.mapElement));
            var lY = (gmaps.map.getDiv().offsetHeight - (gmaps.map.getDiv().offsetHeight/2 + this.overlayProjection.fromLatLngToDivPixel(gmaps.map.getCenter()).y - parseInt(m.style.top))) + map[1] ;
            var lX = (gmaps.map.getDiv().offsetWidth - (gmaps.map.getDiv().offsetWidth/2 + this.overlayProjection.fromLatLngToDivPixel(gmaps.map.getCenter()).x - parseInt(m.style.left))) + map[0] ;

            //show label
            label.style.display='block';

            //set position
            label.style.top = (lY )  + 'px';
            label.style.left = (lX + gmaps.markers[idx].mw+5) + 'px';
            label.innerHTML =  gmaps.markers[idx].hover.replace(/&gt;/gi,">").replace(/&lt;/gi,"<").replace(/&amp;/gi,'&').replace(/&quot;/gi,'"');
            //label.setAttribute('class',gmaps.markers[idx].type);
            //label.setAttribute('className',gmaps.markers[idx].type);

    }

    //helper function for calculating element positions
    MAPOVERLAY.prototype.findPos = function(obj) {
        if (obj.offsetParent) {
            var curleft = obj.offsetLeft
            var curtop = obj.offsetTop
            while (obj = obj.offsetParent) {
                curleft += obj.offsetLeft
                curtop += obj.offsetTop
            }
            return [curleft,curtop];
        }
    }



//create a new gmaps object
var gmaps = new GOOGLEMAPS;


