//==========================================================================
var G_COORD_LNG             = 0;
var G_COORD_LAT             = 1;
//==========================================================================

google.load("maps", "2");

//===============================================================================
function HGMapManager() {
    this.markerStartIndex       = 1;
    this.markerEndIndex         = 1;
    this.mapEltId               = "";
    this.hlistings;
    this.map;
    this.markersLoaded          = false;
    this.hasGeocodedListings    = false;
    this.numMarkers = function() {
        return (this.markerEndIndex - this.markerStartIndex + 1);
    }
    this.markerCounter          = 0;
    this.hasListings            = false;
    this.agentCityState         = "";
}
//==========================================================================
/*  Code sequence...
    
    Google maps API loaded.
    HGMapManager object defined.
    Call initializeHG(); when API has finished loading, i.e. google.setOnLoadCallback(initializeHG);
        Define HGOverlay object.
        Define HGMapManager.loadListings() method.
        Define HGListing object.
        Google browser compatibility check, i.e. if ( GBrowserIsCompatible() ) {
        Instiantiate map, i.e. oHGMapMgr.map = new google.maps.Map2(document.getElementById(oHGMapMgr.mapEltId));
        Call oHGMapMgr.loadListings(), i.e. populate oHGMapMgr with listing data
            For any listings that don't have lat/lng data, geocode.getLocations()
        HGLIsting.setLatLng() set as callback for each geocoder call.
        The last time setLatLng is executed load map and loop through all listings to add overlays. 
        
*/
//==========================================================================
function initializeHG() {
    //======================================================================
    //  HGOverlay "inherits" from google.maps.Overlay(). In order to reference
    //  google.maps.Overlay() we need to wait until the API has fully loaded, 
    //  which we do by defining the object within initializeHG(), which is called
    //  as the result of a google.setOnLoadCallback(initializeHG) call in
    //  featured_home_listings.
    //======================================================================
    function HGOverlay(latlng, label) {
        this.latlng_            = latlng;
        this.color_             = "#999";
        this.backgroundColor_   = "#f1f1f1";
        this.label_             = label;
    }
    //===============================================
    /*  In order for HGOverlay to use the Google Overlay object as a superclass it needs to be
        declared (HGOverlay.prototype = new google.maps.Overlay();) after the API has loaded.
        The way we do this is to set the prototype within initializeHG(), which is called as
        the result of google.setOnLoadCallback. This means that we have to also be aware
        of the scope of the other objects/functions we're using for map processing.
    */
    //===============================================
    HGOverlay.prototype = new google.maps.Overlay();
    //===============================================
    HGOverlay.prototype.initialize = function(map) {
      // Create the DIV representing our rectangle
      var div = document.createElement("div");
      
      div.style.position        = "absolute";
      // Semi-transparent grey background.
      div.innerHTML             = "<div class='map_dyn_icon'>" + this.label_ + "</div>";
      
      map.getPane(G_MAP_MAP_PANE).appendChild(div);
      
      this.map_ = map;
      this.div_ = div;
    }
    //===============================================
    HGOverlay.prototype.calculateDivWidth = function() {
        var intNum          = parseInt(this.label_);
        var int10Power      = Math.floor(Math.LOG10E * Math.log(intNum));
        var intBaseOffset   = 20;
        var intStepSize     = 5;
        
        return ( intBaseOffset + (intStepSize * int10Power) ) + "px";
    }
    //===============================================
    // Remove the main DIV from the map pane
    HGOverlay.prototype.remove = function() {
      this.div_.parentNode.removeChild(this.div_);
    }
    //===============================================
    // Copy our data to a new Rectangle
    HGOverlay.prototype.copy = function() {
      return new Rectangle(this.latlng_, this.weight_, this.color_,
                           this.backgroundColor_, this.opacity_);
    }
    //===============================================
    // Redraw the rectangle based on the current projection and zoom level
    HGOverlay.prototype.redraw = function(force) {
      // We only need to redraw if the coordinate system has changed
      if (!force) return;

      var c1 = this.map_.fromLatLngToDivPixel(this.latlng_);
      
      // Set overlay offsets based on div/icon size.
      this.div_.style.left = (c1.x - 12) + "px";
      this.div_.style.top = (c1.y - 1) + "px";
    }
    //======================================================================
    //  END:    HGOverlay object
    //======================================================================
    
    //======================================================================
    //  BEGIN:  HGMapManager.loadListings() method.
    //      This method is declared here so that it is available within the 
    //      scope of initializeHG().
    //======================================================================
    HGMapManager.prototype.loadListings = function() {
        var strPropName = "";
        var geocoder = new google.maps.ClientGeocoder();
        var intNumMarkers = this.markerEndIndex - this.markerStartIndex + 1;
        
        geocoder.setBaseCountryCode("us");
        this.hlistings = new Array(intNumMarkers);
        var intCounter = 0;
        
        if ( intNumMarkers > 0 ) {
            for ( var i = this.markerStartIndex; i <= this.markerEndIndex; i++ ) {
                strPropName = "listing_" + i;
                if ( typeof(document.getElementById(strPropName)) != "undefined" && document.getElementById(strPropName) != null ) {
                    var oPropElt = document.getElementById(strPropName);
                    
                    // Create object from JSON string rendered as a hidden div for each address.
                    eval("var oTmpAddr = " + oPropElt.innerHTML);
                    
                    var oListing = new HGListing(oTmpAddr, intCounter);
                    if ( (oListing.address.lat.length == 0 || oListing.address.lat == 0) || (oListing.address.lng.length == 0 || oListing.address.lng == 0) ) {
                        // Get lat/lng from geocoder. We'll add the property to the list in the handleGetLocations() callback.
                        geocoder.getLatLng(oListing.getAddress(), oListing.setLatLng);
                    }
                    else {
                        // Add property to an array of properties.
                        this.hlistings[oListing.index] = oListing;
                        
                        oListing.setLatLng(new google.maps.LatLng(oListing.address.lat, oListing.address.lng));
                    }
                }
                intCounter += 1;
            }
        }
        else {
            this.map.setCenter(new google.maps.LatLng(39.83333, -98.58333), 3);
            this.addControls();
        }
    }
    HGMapManager.prototype.addControls = function() {
        /*
        Constructor                     Description 
        GSmallMapControl()              Creates a control with buttons to pan in four directions, and zoom in and zoom out. 
        GLargeMapControl()              Creates a control with buttons to pan in four directions, and zoom in and zoom out, and a zoom slider. 
        GSmallZoomControl()             Creates a control with buttons to zoom in and zoom out. 
        GScaleControl()                 Creates a control that displays the map scale. 
        GMapTypeControl()               Creates a standard map type control for selecting and switching between supported map types via buttons. 
        GMenuMapTypeControl()           Creates a drop-down map type control for switching between supported map types. 
        GHierarchicalMapTypeControl()   Creates a "nested" map type control for selecting and switching between supported map types via buttons and nested checkboxes. 
        GOverviewMapControl()           Creates a collapsible overview mini-map in the corner of the main map for reference location and navigation (through dragging). The GOverviewMapControl creates an overview map with a one-pixel black border. 

        */
        this.map.addControl(new google.maps.SmallMapControl());
        this.map.addControl(new google.maps.MenuMapTypeControl());
    }
    //===============================================
    HGMapManager.prototype.zoomToCity = function() {
        var geocoder = new google.maps.ClientGeocoder();
        
        if ( this.agentCityState.length > 0 ) {
            geocoder.getLatLng(this.agentCityState, getCityPoint);
        }
        else {
            this.map.setCenter(new google.maps.LatLng(39.83333, -98.58333), 3);
            this.addControls();
        }
    }
    //===============================================
    function getCityPoint(obj_point) {
        if ( obj_point ) {
            oHGMapMgr.map.setCenter(obj_point, 11);
            oHGMapMgr.addControls();
        }
        else {
            oHGMapMgr.map.setCenter(new google.maps.LatLng(39.83333, -98.58333), 3);
            oHGMapMgr.addControls();
        }
    }
    //======================================================================
    //  END:  HGMapManager.loadListings() method.
    //======================================================================
    
    //======================================================================
    //  BEGIN:  HGListing object.
    //======================================================================
    function HGListing(address, index) {
        this.address    = address;
        this.index      = ( index ? index : 0 );
        var objListing  = this;
        
        // Declaring setLatLng() here creates a closure and allows us to access
        // the object and its properties when called as the result of the getLatLng() callback.
        this.setLatLng  = function(obj_point) {
            if ( obj_point && obj_point.y > 0 && ( obj_point.x < -45.0 && obj_point.x > -180.0 ) ) {
                objListing.address['lat'] = obj_point.y;
                objListing.address['lng'] = obj_point.x;
                
                oHGMapMgr.hasGeocodedListings = true;
            }
            
            // Add object listing to HGMapManager list.
            oHGMapMgr['hlistings'][objListing.index] = objListing;
            
            var intNumMarkers = oHGMapMgr.markerEndIndex - oHGMapMgr.markerStartIndex + 1;
            
            oHGMapMgr.markerCounter += 1;
            // After all listings have been processed center the map, etc.
            //if ( objListing.index == (intNumMarkers - 1) ) {
            if ( oHGMapMgr.markerCounter == intNumMarkers ) {
                oHGMapMgr.map.setCenter(new google.maps.LatLng(39.83333, -98.58333), 3);
                /*  Note: If you don't call setCenter() before addControl() (and possibly other methods) you'll get a "'this.G' is null
                    or not an object." error.
                */
                oHGMapMgr.addControls();
                oHGMapMgr.markersLoaded = true;
                
                var oPoints = new Array();
                var oPrevPoint, oCurrPoint;
                var intCounter = intNumMarkers;
                
                for ( var i = oHGMapMgr.markerEndIndex; i >= oHGMapMgr.markerStartIndex; i-- ) {
                    if ( typeof(oHGMapMgr['hlistings'][intCounter - 1]) != 'undefined' ) {
                        var oListing = oHGMapMgr['hlistings'][intCounter - 1];
                        var oIconDiv = document.getElementById("hlisting_address_icon_" + oListing.address['ui_id']);
                        
                        oIconDiv.innerHTML = oListing.address['ui_id'];
                        
                        if ( oListing.address['lat'] != 0 && oListing.address['lng'] != 0 ) {
                            // This listing has lat/lng data.
                            oCurrPoint = new google.maps.LatLng(oListing.address['lat'], oListing.address['lng']);
                            
                            oPoints.push(oCurrPoint);
                            
                            var oHGOlay = new HGOverlay(oCurrPoint, oListing.address['ui_id']);
                            var oMarkerConfig = {
                                'click_url'         : oListing.address.listing_url,
                                'listing_elt_id'    : 'hlisting_row_' + oListing.address.listing_uid
                            }
                            
                            oListing.addMarker(oCurrPoint, oMarkerConfig);
                            oHGMapMgr.map.addOverlay(oHGOlay);
                            oIconDiv.className = "hlisting_icon hlisting_icon_img";
                        }
                        else {
                            // This listing does not have lat/lng data.
                        }
                    }
                    else {
                        var oIconDiv = document.getElementById("hlisting_address_icon_" + i);
                        
                        oIconDiv.innerHTML = i;
                        oIconDiv.className = "hlisting_icon hlisting_icon_img_nomap";
                    }
                    intCounter -= 1;
                }
                
                // Only if we have at least one geocoded listing do we want to re-center and zoom.
                if ( oHGMapMgr.hasGeocodedListings ) {
                    /*  Get the center of the listing points and center and zoom the map.
                    
                        We need a LatLngBounds object to pass to map.getBoundsZoomLevel() method and we're starting with
                        a collection of points. We'll first get a Bounds object, then convert that to a LatLngBounds object.
                    */
                    var oGBounds = new google.maps.Bounds(oPoints); // Get bounds based on our collection of points.
                    var oSW = new google.maps.LatLng(oGBounds.maxY, oGBounds.minX); // Get the southwestern-most point of the bounding box.
                    var oNE = new google.maps.LatLng(oGBounds.minY, oGBounds.maxX); // Get the northeastern-most point of the bounding box. 
                    var oGLLBounds = new google.maps.LatLngBounds(oSW, oNE); //  Get the LatLngBounds object.
                    
                    // Re-center/zoom the map based on the LatLngBounds object.
                    oHGMapMgr.map.setCenter(oGLLBounds.getCenter(), oHGMapMgr.map.getBoundsZoomLevel(oGLLBounds));
                }
                else {
                    oHGMapMgr.zoomToCity();
                }
            }
        }
    }
    //===================================================
    HGListing.prototype.addMarker = function(point, obj_config) {
        // To make our overlay clickable we'll add a transparent marker and add a click event listener to it. 
        var clearIcon = new GIcon();
        //clearIcon.image = "http://fppzn81.homegain.com/jc/image/clear.png";
        clearIcon.image = "/images/clearpixel";
        clearIcon.iconSize = new GSize(27, 18);
        clearIcon.iconAnchor = new GPoint(2, 0);
        //clearIcon.shadow = "http://fppzn81.homegain.com/jc/image/icon_house_w_shadow.png";
        
        var marker = new google.maps.Marker(point, { icon : clearIcon } );
        var this_obj = this;
        
        this.marker = marker;
        
        GEvent.addListener(this.marker, "click", function() {
            document.location.href = obj_config['click_url'];
        });
        GEvent.addListener(this.marker, "mouseover", function() {
            // Highlight listing row.
            document.getElementById(obj_config['listing_elt_id']).style.backgroundColor = '#fffdc4'; //'#ffcb00'; //'#fffecf';
        });
        GEvent.addListener(this.marker, "mouseout", function() {
            // Highlight listing row.
            document.getElementById(obj_config['listing_elt_id']).style.backgroundColor = '#fff';
        });
        
        oHGMapMgr.map.addOverlay(this.marker);
    }
    //===============================================
    HGListing.prototype.getAddress = function() {
        return this.address['street_address'] + ", " + this.address['city'] + ", " + this.address['state'] + ", " + this.address['zip'];
    }
    //======================================================================
    //  BEGIN:  HGListing object.
    //======================================================================
    if ( GBrowserIsCompatible() ) {
        oHGMapMgr.map = new google.maps.Map2(document.getElementById(oHGMapMgr.mapEltId));
        oHGMapMgr.map.enableContinuousZoom();
        
        if ( oHGMapMgr.hasListings ) {
            // Load hlisting data.
            oHGMapMgr.loadListings();
        }
        else {
            oHGMapMgr.zoomToCity();
        }
    }
}
//================================================================
var oSTFConfig = {
        stf_id      : '',
        subject     : '',
        address     : '',
        city        : '',
        state       : '',
        zip         : '',
        data        : ''
    };

function openSendToFriendWindow() {
    var strURLToForward = escape(document.location.href);
    var strStreetAddress = "No street address spcified.";
    var strQS = "";
    
    for ( var prop in oSTFConfig ) {
       strQS += "&" + prop + "=" + escape(oSTFConfig[prop]);
    }
    
    window.open('/popup/send-link-via-email?url_to_forward=' + strURLToForward + strQS, 'forwardToFriendWin', 'width=425,height=505,status=0,scrollbars=0,resizable=1,toolbar=0,location=0');
}
//===============================================================================

