
var PolygonHandlers = {
		lastTimeout : null,
		lastPoly: null,
		
	    zipPopupTitle : {ForeclosureCount: 'Foreclosures: ', AvgHomeValue: 'Avg. Home Value: '},
	    zipPopupFormat: {ForeclosureCount: '', AvgHomeValue: '$'},
	    

	    hideTooltip : function () {
			var tooltip = document.getElementById('polygonTooltip');
			if ( tooltip ) {
				tooltip.style.visibility = 'hidden';
			}
			if ( PolygonHandlers.lastPoly ) {
				//PolygonHandlers.lastPoly.setFillStyle({opacity:0.3});
				PolygonHandlers. lastPoly = null;
			}
			if ( PolygonHandlers.lastTimeout ) {
				clearTimeout(PolygonHandlers.lastTimeout);
				PolygonHandlers.lastTimeout = null;
			}
			
		},
		
		mouseOver: function() {
			// when google map calls us 'this' is set to the current polygon
			// save it for the timeout handler
			PolygonHandlers.lastPoly = this;
			// disable polygon highlighting for now
			//this.setFillStyle({opacity:0.6});
			if ( PolygonHandlers.lastTimeout ) {
				clearTimeout(PolygonHandlers.lastTimeout);
			}
			PolygonHandlers.lastTimeout = setTimeout("PolygonHandlers.showPopup()", 1000);
		},
		
		showPopup : function() {
			PolygonHandlers.lastTimeout = null;
			var poly = PolygonHandlers.lastPoly;
			var map = searchControl.mainMap;			
			var proj = map.getCurrentMapType().getProjection();
			var point1 = proj.fromLatLngToPixel(map.getBounds().getSouthWest(),map.getZoom());
			var point2 = proj.fromLatLngToPixel(map.getBounds().getNorthEast(),map.getZoom());
			var offset= proj.fromLatLngToPixel(poly.getBounds().getCenter(),map.getZoom());
			var wantedX = offset.x - point1.x;
			var wantedY = offset.y - point2.y; 
			var tooltip = document.getElementById('polygonTooltip');
			if ( !tooltip ) {
				tooltip =  document.createElement("DIV");
				tooltip.id = 'polygonTooltip';
				document.getElementById('mapPane').appendChild(tooltip);
			}
			var mapView = document.getElementById('map_view');
			if ( wantedX > mapView.clientWidth-200 ) {
				wantedX = mapView.clientWidth - 200;
			}
			if ( wantedY > mapView.clientHeight-100 ) {
				wantedY = mapView.clientHeight - 100;
			}
			if ( wantedX < 100 ) {
				wantedX = 100;
			}
			if ( wantedY < 20 ) {
				wantedY = 20;
			}
			
			var ta=[], ti=0;
			ta[ti++] = "<h1>Click and drag your mouse to move the map</h1>";
			ta[ti++] = "<br />";
			ta[ti++] = "<table><tr><td>Zip: </td><td style='text-align: left; color:#000000;'> ";
			ta[ti++] = poly.geo.name;
			ta[ti++] = "</td></tr>" 
			var heatMap = poly.geo.heatMap;
			if ( poly.geo.heatMap ) {
				for ( var vi=0;vi<poly.geo.heatMap.values.length;vi++ ) {
					var v = poly.geo.heatMap.values[vi];
					if ( typeof(v) != "undefined" && v!== null ) {
						ta[ti++] = "<tr><td>";
						ta[ti++] = PolygonHandlers.zipPopupTitle[poly.geo.heatMap.valueLabels[vi]];
						ta[ti++] = "</td><td style='text-align: left; color:#000000;'>"
						ta[ti++] = PolygonHandlers.zipPopupFormat[poly.geo.heatMap.valueLabels[vi]];
						ta[ti++] = dojo.number.format(poly.geo.heatMap.values[vi]);
						ta[ti++] = "</td></tr>";
					}
				}
			};
			ta[ti++]="<tr><td colspan='2'><a href='#' onclick='mapControl.showListingsInZip(";
			ta[ti++]=poly.geo.name;
			ta[ti++]=");return false;'";
			ta[ti++]=">Show Foreclosures</a></td></tr></table>";
			tooltip.innerHTML = ta.join('');
			tooltip.style.visibility = 'visible';
			tooltip.style.position = 'absolute';
			tooltip.style.top = wantedY + "px";
			tooltip.style.left = wantedX+"px";
			//console.log("Wanted X " + wantedX + " mapview " + mapView.clientWidth );
		},
		
		mouseOut : function() {
			PolygonHandlers.hideTooltip();
		},
		
		handleNewView : function() {
			PolygonHandlers.hideTooltip();			
		}
};



function RememberZoomControl(_mapControl) {
	this.mapControl = _mapControl;
	this.container = null;
}

RememberZoomControl.prototype = new GControl();

RememberZoomControl.prototype.initialize = function(map) {
	  this.container = document.createElement("div");
	  this.container.style.display = 'none';

	  var backDiv = document.createElement("div");
	  backDiv.id = 'previousMapButton';
	  
	  this.container.appendChild(backDiv);
	  var img = document.createElement("img");
	  img.setAttribute("src","/web/images/back.png");
	  backDiv.appendChild(img);
	  var me = this;
	  GEvent.addDomListener( img, "click", function() {
		 me.mapControl.popZoom();
	  });

	  map.getContainer().appendChild(this.container);
	  return this.container;
};

RememberZoomControl.prototype.hide = function() {
	if ( this.container ) {
		this.container.style.display = 'none';
	}
};

RememberZoomControl.prototype.show = function() {
	if ( this.container ) {
		this.container.style.display = 'block';
	}
};

RememberZoomControl.prototype.getDefaultPosition = function() {
	  return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(40, 30));
};


/**
 * Custom zoom control.
 */
function FAMapControl(parent) {
    this.map = null;
    this.parent = parent;
}

// To "subclass" the GControl, we set the prototype object to
// an instance of the GControl object
FAMapControl.prototype = new GControl();

FAMapControl.prototype.switchToMapZoomLevel=14;
FAMapControl.prototype.switchToPhysicalZoomLevel=11;

FAMapControl.prototype.handleZoomEvent = function(evt) {
    var z = evt.target.attributes['data_id'].value;
    var existing = this.map.getZoom();
    if ( z == "minus" ) {
        z = existing -1;
    } else if ( z == "plus" ) {
        z = existing + 1;
    }
    // setting the zoom directly does not seem to work
    // this.map.setZoom(z);

    // so instead remove the event listeners, move the map then put back the event listeners
    if ( Math.abs(existing-z) > 1 ) {
        this.parent.unhook();
    }
    while( existing > z ) {
        if ( Math.abs(existing-z) == 1 ) {
            this.parent.hookup();
        }
        this.map.zoomOut();
        existing--;
    }
    while( z > existing ) {
        if ( Math.abs(existing-z) == 1 ) {
        	if ( z >= this.switchToMapZoomLevel ) {
        	    this.map.setMapType(G_NORMAL_MAP);
        	}
        	if ( z<=this.switchToPhysicalZoomLevel ) {
        		this.map.setMapType(G_PHYSICAL_MAP);
        	}
            this.parent.hookup();
        }
        this.map.zoomIn();
        existing++;
    }
}

FAMapControl.prototype.markZoomLevel = function(level) {
    dojo.query('.zoomSelected').removeClass('zoomSelected');
    dojo.query('#faMapControl_' + level).addClass('zoomSelected');
}

FAMapControl.prototype.initialize = function(map) {
    this.map = map;
    var that = this;
    var container = document.createElement("div");
    container.setAttribute("id","zoom-view");
    var levels = [["Widest", 9], ["Wide",10], ["County", 11], ["City", 12], ["Zip", 13], 
                   ["Street", 14],["Block", 15], ["House", 16]];
	var isIE = /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent);
    if ( isIE ) {
        // IE can't handle all the zoom levels, eliminate some
        levels.splice(0,2);
    } 
    while ( levels.length > 2 && RENDER.minZ > levels[0][1]) {
    	// eliminate more zoom level if required by the more pref (HX vs. FA)
    	levels.splice(0,1);
    }

    // handler to set 'this' for the method
    var zoomHandler = function(evt) {
        evt.target.style.backgroundImage = "";
        that.handleZoomEvent(evt);
    }
    
    var freespaceDiv = document.createElement('div');
    container.appendChild(freespaceDiv);
    
    var plusDiv = document.createElement('div');
    plusDiv.setAttribute("id","plusDivControl");
    plusDiv.setAttribute("data_id","plus");
    dojo.connect(plusDiv,"click", zoomHandler );
    container.appendChild(plusDiv);
    
    for (var i=0; i < 8; i++) {
        var desc = levels[16-i];
        var wanted = 16-i;
        var zoomDiv = document.createElement('div');
        zoomDiv.setAttribute('data_id',  wanted);
        zoomDiv.setAttribute( 'id', 'faMapControl_' + wanted );
        container.appendChild(zoomDiv);
        dojo.connect(zoomDiv, "click", zoomHandler);
		dojo.connect(zoomDiv, "onmouseover", zoomOver);
		dojo.connect(zoomDiv, "onmouseout", zoomOut);
    };
    
    var minusDiv = document.createElement('div');
    minusDiv.setAttribute("id","minusDivControl");
    minusDiv.setAttribute("data_id","minus");
    dojo.connect( minusDiv,"click", zoomHandler );
    container.appendChild(minusDiv);

    map.getContainer().appendChild(container);
    
    dojo.query('#plusDivControl').addClass('control');
    dojo.query('#minusDivControl').addClass('control');
	
    return container;
}

function zoomOver(evt) {
	if ( evt.target.className.indexOf("zoomSelected") == -1 ) {    
	    evt.target.style.backgroundImage = "url(/web/images/09/zoom_level_base_hover.png)";
    }
}

function zoomOut(evt) {
	if ( evt.target.className.indexOf("zoomSelected") > -1 ) {
       // don't set the background it will be set by the css
	} else {
	   evt.target.style.backgroundImage = "";
	}
}

FAMapControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(0, 0));
}


dojo.declare("com.foreclosureagency.MapController",null,  {
	polyColors: ['#9C0','#FC0','#9933C0','#F30','#03F','#93F','#FCF','#F60','#C03399','#C0FFFF','#0cf'],
    tooltip:null,
    icons: { reo:null,pre:null,auc:null,best:null,other:null, camera: null}, 
    clusterer:null,
    existingMarkers:null,
    mapHistory: [],
    map: null,
    rememberZoomControl: null,
	neighborhoodPolyGons :null, // Neighborhood GPolygon objects    
    lastDetail: {}, // information about the listing last displayed in the detail window
    heatColorGenerator: new HeatColorGenerator.Interval(),
    mapLegend: new MapLegend("heat_map"),
    mapListeners: [], // listeners hooked up to this map
    
    
    createIcon: function  (url) {
        var icon = new GIcon();        
        icon.image = url;
        icon.shadow = '/web/images/house-multiples-shadow.png';
        icon.iconSize = new GSize( 44, 42 );
        icon.shadowSize = new GSize( 65, 42 );
        icon.iconAnchor = new GPoint( 13, 34 );
        icon.infoWindowAnchor = new GPoint( 13, 34 );
        icon.infoShadowAnchor = new GPoint( 27, 34 );
        return icon;
    },

    rememberZoom : function(  ) {
    	var save = {center: this.map.getCenter(), zoom: this.map.getZoom() };
    	if ( this.mapHistory.length > 0 ) {
    		var top = this.mapHistory[this.mapHistory.length-1];
    		if ( top && top.center && save.center && top.center.distanceFrom(save.center)<200) {
    			//don't save duplicate zoom
    			return;
    		}
    	}
		this.mapHistory.push(save);
		this.rememberZoomControl.show();
    },
    
    popZoom : function () {
    	if ( !this.mapHistory || !this.mapHistory.length ) {
    		var zoom = this.map.getZoom();
    		if ( zoom > RENDER.mZ ) {
    			this.map.setZoom( RENDER.mZ );
    		}
    		return;
    	}
    	var todo = this.mapHistory[this.mapHistory.length-1];
    	this.mapHistory.length--;
    	if ( todo.zoom > RENDER.mZ) {
    		todo.zoom = RENDER.mZ;
    	}
    	this.map.setCenter( todo.center, todo.zoom );
    	if ( this.mapHistory.length > 0 ) {
    		todo = this.mapHistory[this.mapHistory.length-1];
    		if ( todo.tab ) {
    			this.mapHistory.length--;
    			searchControl.selectSubTab(todo.tab);
    		}
    	}
    	searchControl.resetFeaturedListing();
    	if ( this.mapHistory.length === 0 ) {
    		this.rememberZoomControl.hide();
    	}
    },
    
    trackMapHistory: function(center,zoom) {
    	if ( this.mapHistory.length === 0 ) {
    		return null;
    	}
    	var top = this.mapHistory[this.mapHistory.length-1];
    	if ( !top ) {
    		return null;
    	}
    	// check if we have stored the wanted zoom and position
    	if ( !top.wantedZoom || !top.wantedCenter ) {
    		if ( center ) {
    			top.wantedCenter = center;
    		}
    		if ( zoom ) {
    			top.wantedZoom = zoom;
    		}
    		return null;
    	}
    	return top;
    },
    
    /**
     * Reset the map history when the settings move far enough from the top of the stack.
     */
    resetMapHistory: function (center,zoom) {
    	var top = this.trackMapHistory(center,zoom);
    	if ( !top ) {
    		return;
    	}
    	if ( top.wantedZoom != zoom || center.distanceFrom(top.wantedCenter)>46000) {
        	this.mapHistory.length = 0;
    	}
    	// make sure there is a real place to jump to
    	if ( top.wantedZoom && top.wantedCenter ) {
    		if ( top.wantedZoom == top.zoom && top.center.distanceFrom(top.wantedCenter)<1000) {
    			this.mapHistory.length--;
    		}
    	}
    	if ( this.mapHistory.length === 0 ) {
    		this.rememberZoomControl.hide();
    	}
    },
    
    /**
     * Handle the map move event from the Google map.
     */
    mapMoveEndHandler: function() {
    	var mb = this.map.getBounds();
    	var mz = this.map.getZoom();
    	searchControl.handleNewView( mb, mz );
    	this.faMapControl.markZoomLevel(mz);
    },

    /**
     * Pop the zoom later when we are out of the event handler.
     */
    popLater : function () {
    	var that=this;
		setTimeout(function(){that.popZoom(); upgradeDialog.show();},50);

    },
    
    mapDragEndHandler: function() {
    	var mb = this.map.getBounds();
    	var mz = this.map.getZoom();
    	searchControl.onMapMovedByUser(mb,mz);
    	var mc = this.map.getCenter();
    	if ( this.map.getZoom() > RENDER.mZ )  {
    		var top = this.trackMapHistory(mc, mz);
			if ( this.mapHistory.length == 0 ) {
				this.popLater();
			}
    		if ( top && top.center.distanceFrom(mc)>200 && (!top.wantedCenter || top.wantedCenter.distanceFrom(mc)>200) ) {
    			this.popLater();
    		}
			return;
    	}
        this.resetMapHistory( mc, mz );
    },
    
    /**
     * Handle a map zoomend event.
     */
    mapZoomEndHandler :  function() {
    	var nzoom = this.map.getZoom();
    	this.faMapControl.markZoomLevel(nzoom);
		if ( nzoom > RENDER.mZ && this.mapHistory.length == 0 ) {
			this.map.setZoom(RENDER.mZ);
			upgradeDialog.show();
			return;
		}
    	searchControl.handleNewView( this.map.getBounds(), nzoom );
    	this.resetMapHistory( this.map.getCenter(), this.map.getZoom());
    },


    initIcons: function () {
    	this.icons.reo = this.createSingleIcon('housex-red.png');
    	this.icons.pre = this.createSingleIcon('housex-orange.png');
    	this.icons.auc = this.createSingleIcon('housex.png');
    	this.icons.other = this.createSingleIcon('housex.png');
    	this.icons.best = this.createSingleIcon('spotlight-house.png');
    	this.icons.camera = this.createSingleIcon('camera.png');
    	this.icons.camera.shadow = '';
    },

    createSingleIcon: function (image){
        var iconSingle = new GIcon();
        iconSingle.image = "/web/images/map/" + image;
        iconSingle.shadow = "/web/images/map/housex-shadow.png";
        iconSingle.iconSize = new GSize(40, 40);
        iconSingle.shadowSize = new GSize(60, 40);
        iconSingle.iconAnchor = new GPoint(20, 44);
        iconSingle.infoWindowAnchor = new GPoint(20, 40);
        iconSingle.infoShadowAnchor = new GPoint(20, 40);
        return iconSingle;
    },

    /**
     * Function called by google maps to compute the z-index for a marker
     */
    markerOrder : function (marker,b) {
    	return 9999999;
    },

    createMarker: function ( listing, type, map, point,zoom ) {
        //create the marker with the appropriate icon
        markerOptions = { 
            icon:this.getIcon( type, zoom, false ),
            text: (RENDER.address?RENDER.address:listing.address)	
        };
        if ( type == 'best' ) {
        	markerOptions.zIndexProcess = this.markerOrder;
        }
        var marker;

        var latlng = new GLatLng(listing.lat,listing.lon);
        marker = new GMarker( latlng, markerOptions );
        marker.listing_id = listing.id;
        marker.markerType = type;

        var me = this;
        GEvent.addListener(marker,"click", function() {
              me.showDetail(listing.id,listing.entityType);
            });

	    if ( typeof marker.setMap == "function" ) {
	    	marker.setMap( map );
	    }

	    var title=[], ti=0;
	    
        title[ti++] = "<a href='#' onclick='mapControl.showDetail("+listing.id+", \""+ listing.entityType+"\");'>";
        var markerDetail;
        if ( RENDER.addressInMarkerTitle) {
        	var md=[],mdi=0;
        	md[mdi++]=listing.address;
        	md[mdi++]='<br />';
        	md[mdi++]=listing.city;
        	md[mdi++]=", ";
        	md[mdi++]=listing.state;
        	if ( listing.minBid ) {
	        	md[mdi++] = '<br /> $';
	        	md[mdi++] = dojo.number.format(listing.minBid);
        	}
        	markerDetail = md.join('');
        } else {
        	if ( listing.minBid ) {
	        	markerDetail="$"+dojo.number.format(listing.minBid)+", ";
        	} else {
        		markerDetail='';
        	}
        	markerDetail=markerDetail+listing.zip;
        }
        title[ti++] = markerDetail;
        title[ti++]='</a>';
        marker.title = title.join('');
        marker.onMap = false;
        marker.minBid = listing.minBid;
        if ( searchControl.featuredListingId == marker.listing_id && RENDER.addressInMarkerTitle) {
        	marker.isFeatured = markerDetail;
        	//c_onsole.log( 'found featured marker, setting isFeatured to ' + markerDetail);
        }

        return marker;
    },




    getIcon: function (type, zoom) {
    	if ( !type ) {type = 'other';}
        var icon = this.icons[type.toLowerCase()];
        if ( !icon ) {icon = this.icons.other;}
        return icon;
    },
    
    /**
     * Bring up the UI to create a forum message.
     */
    createForumMessage: function(mouseEvent) {
    	var coords = document.getElementById('createForumMessageCoords');
    	coords = mouseEvent.clientX + " " + mouseEvent.clientY;
    	coords.innerHtml = coords;
    	createForumMessageDialog.show();
    },
    
    /**
     * Add a street view in the given div.
     */
    addStreetView: function(streetDiv, latlng) {
        if ( streetDiv ) {
            var streetClient = new GStreetviewClient();
            var that = this;
            var ret = streetClient.getNearestPanorama(latlng,function(nearest){
        		if ( nearest && nearest.code == 200 ) {
        			
        			var yaw = LatLon.bearing( nearest.location.lat, nearest.location.lng, latlng.lat(), latlng.lng() );
        			//c_onsole.log( 'computed yaw ' + yaw + " interest " + latlng + " view " + nearest.location.latlng );
					that.lastDetail.panorama = new GStreetviewPanorama(streetDiv, {latlng: latlng, pov: {yaw: yaw}});
        			if ( !RENDER.useVirtualEarth ) {
						//, {icon: that.icons.camera, text: "Street View"}
						var cameraMarker = new GMarker( nearest.location.latlng);
						that.lastDetail.satelliteMap.addOverlay(cameraMarker);
	        			that.lastDetail.satelliteMap.addOverlay(new GStreetviewOverlay());
						GEvent.addListener( that.lastDetail.panorama, 'initialized', function(streetViewLocation) {
							cameraMarker.setLatLng( streetViewLocation.latlng );
							/*
		        			var yaw = LatLon.bearing( streetViewLocation.lat, streetViewLocation.lng, latlng.lat(), latlng.lng() );
		        			GStreetviewPanorama.setPOV({yaw: yaw});
		        			*/
						});
					}
        		} else {
            		streetDiv.innerHTML = "There is no street view information for this location.";
        		}
        		
            });
        }
    },

    /**
     * Add a satellite view in the given div
     */
    addSatelliteView: function(satDiv,lat,lng) {
		if ( !this.lastDetail ) {
			this.lastDetail = {};
		}    	
		if ( RENDER.useVirtualEarth ) {
		    var latlngVE = new VELatLong(lat, lng);
		    var map = new VEMap(satDiv.id);
		    map.HideDashboard();
		    map.HideScalebar();
		    map.LoadMap(latlngVE, 17);
	        // switch to birds eye if available
	        map.AttachEvent("onobliqueenter", function (){
	            if(map.IsBirdseyeAvailable()) {
	               map.SetBirdseyeScene(latlng);
	            }
	         });
		} else {
			var latlng = new GLatLng(lat, lng);
	        var detmap = new GMap2(satDiv);
	        detmap.setMapType(G_SATELLITE_MAP);
	        detmap.setCenter( latlng, 13);
	        detmap.setZoom(detmap.getCurrentMapType().getMaximumResolution()-1);
	        //GEvent.addListener(detmap,'click', mapControl.closeDetail );
	        var marker = new GMarker( latlng, {icon: mapControl.icons.best} );
	        detmap.addOverlay(marker);
	        this.lastDetail.satelliteMap = detmap;	        
		}
    },

    /** 
     *  Check that the photo url can be loaded.
     */
    verifyPictureDownload : function() {
        var checkCount = 15;
        var interval = setInterval ( function() {
            var photoBox = dojo.byId('listingDetailPhotoBox');
            if ( !photoBox || checkCount--<0 ) {
            	clearInterval( interval );
            	return;
            }
        	var imgs = dojo.query("img", photoBox );
        	if ( imgs && imgs.length ) {
        		var img = imgs[0];
        		var loaded = false;
        		if ( typeof img.naturalHeight == "undefined") {
        			var lgi = new Image();
                    lgi.src = img.src;
                    if ( lgi.height > 1 ) {
                    	loaded = true;
        			}
        		} else  if ( img.naturalHeight > 1 ) {
        			loaded = true;
        		}
        		if ( loaded ) {
        			photoBox.style.display = 'block';
                	clearInterval( interval );
        		}
            }
        }, 200 );
    },
    
    /**
     * Handle the listing/auction detail data coming from the backend.
     * The data comes formatted in html format.
     */
    showDetailHandler : function(response) {
    	Public.progressIndicator.hide();
    	searchControl.dequeueActions();
    	dojo.byId("detailPane").innerHTML = response;
    	/*
        listingDetailDialog.setContent(response);
    	try { 
	        listingDetailDialog.show();
	        listingDetailDialog.layout();
    	} catch ( e ) {
    	}
    	*/
        var titleDiv = document.getElementById('detailTitle');
        if ( titleDiv && titleDiv.firstChild ) {
            var title = titleDiv.firstChild.nodeValue;
            listingDetailDialog.titleNode.innerHTML =  title;
        }

        // display the sattelite map
    	var satDiv = dojo.byId('map-satellite');
    	if ( !satDiv ) {
    		return;
    	}
    	var lat = satDiv.attributes.data_lat.value;
    	if (  lat ) {
            var latlng = new GLatLng(lat, satDiv.attributes.data_lon.value);
            this.addSatelliteView(satDiv,lat, satDiv.attributes.data_lon.value);
            var streetDiv = dojo.byId('map-street');
            this.addStreetView(streetDiv, latlng);	                
    	} else {
    		satDiv.style.display = 'none';
    	}
    	this.verifyPictureDownload();
    },
    

    
    removeExistingPolygons: function() {
    	PolygonHandlers.hideTooltip();
        if ( searchControl.neighborhoodPolyGons && searchControl.neighborhoodPolyGons.length > 0 ) {
        	//console.log( "Removing " + searchControl.neighborhoodPolyGons.length + " polygons ");
        	for ( i=0;i<searchControl.neighborhoodPolyGons.length;i++ ) {
        		var one = searchControl.neighborhoodPolyGons[i];
        		this.map.removeOverlay( one );
    		}
    	}
    	//c_onsole.log( "geoOnMap: reusing " + newList.length + " polygons out of " + searchControl.neighborhoodPolyGons.length );
        searchControl.neighborhoodPolyGons = [];
    },
    
    /**
     * Build a hash with the id-s of the element in the array to increase performance.
     */
    buildHashForId : function(arr) {
    	var built = {};
    	if( !arr || !arr.length ) {
    		return built;
    	}
    	for( var i=0;i<arr.length;i++) {
    		built["id"+arr[i].id] = i+1;
    	}
    	return built;
    }    

});

/**
 * 
 */
com.foreclosureagency.MapController.prototype.geoOnMap=function(geoList,stats,title,zoom) {
	if ( !geoList || !geoList.length ) {
		// no data, bail out
        this.mapLegend.noContent();
		return;
	}
   if ( stats && stats.values && stats.values.length && stats.values.length>3 && title ) {
       // only display the legend if there is a title
       this.heatColorGenerator.analyze(stats.values, stats.activeIndex);
       this.mapLegend.displayContent(title,this.heatColorGenerator.generateLegend());
   } else {
       this.mapLegend.noContent();
   }
   var existingPoly = this.buildHashForId(searchControl.neighborhoodPolyGons);
   var newPoly = this.buildHashForId(geoList);
   
   // remove the existing polygons that are not part of the new list
   var removeTime = new Date().getTime();
   if ( searchControl.neighborhoodPolyGons && searchControl.neighborhoodPolyGons.length > 0 ) { 
   	var newList = [];
   	for ( i=0;i<searchControl.neighborhoodPolyGons.length;i++ ) {
   		var one = searchControl.neighborhoodPolyGons[i];
   		if ( !newPoly["id"+one.id]) {
       		GEvent.addListener( one,'mouseover', PolygonHandlers.mouseOver );
       		GEvent.addListener( one,'mouseout', PolygonHandlers.mouseOut );
   			searchControl.mainMap.removeOverlay( one );   			
   		} else {
   			newList.push(one);
   		}
   	}
   	searchControl.neighborhoodPolyGons = newList;
   	ourPolygons = newList;
   }
	
	this.displayGeoState = {
			geoList: geoList,
			stats: stats,
			title: title,
			zoom: zoom,
			index: 0,
			existingPoly: existingPoly,
			removeTime: new Date().getTime() - removeTime
	}
   mapControl.do_geoOnMap();
	
}
	
com.foreclosureagency.MapController.prototype.do_geoOnMap=function() {
	//console.log( "Entering geo on map");
	var geoList=this.displayGeoState.geoList,stats=this.displayGeoState.stats,title=this.displayGeoState.title,zoom=this.displayGeoState.zoom;	
	var existingPoly = this.displayGeoState.existingPoly;
	var polygonOutline = true;
	var polygonOpacity = 0.3;
	if ( zoom < 11 ) {
		polygonOpacity = 0.3; // was 0.7
		polygonOutline = false;
	}
	
   var ourPolygons = [];
   var i = 0,p = 0,boundary = null;
   var mapBoundary = null,points = [],pointArr = [];
   var record = null,point = null,originalColor = '';

   var enterTime = new Date().getTime();
   var totalAO = 0;
   var totalPoints = 0;
   var map = searchControl.mainMap;
   for (i = 0; i < geoList.length; ++i) {
       boundary = geoList[i];

       if ( existingPoly["id"+boundary.id]  ) {
       	continue;
       }
       
       if (boundary) {
           var boundaryPolygons=[];
           
           if ( boundary.boundary ) {
	           	mapBoundary = boundary.boundary;
	           	boundaryPolygons = boundary.boundary.polygons;
           }
          	if ( title ) {
           		originalColor = this.heatColorGenerator.generateColor(stats.values[i][stats.activeIndex]);
           	} else {
           		originalColor = this.polyColors[(boundary.id?boundary.id:i) % 11];
           	}
           //console.log("-----" + boundaryPolygons.length + "-------");
           for ( var bp=0;bp<boundaryPolygons.length;bp++) {
           	var inputPolygon = boundaryPolygons[bp];
       		if ( !inputPolygon.levels ) {
       			continue;
       		}
           	var polygon;
       		polygon = new GPolygon.fromEncoded({
       			polylines:[{
       				points:inputPolygon.points,
       				levels:inputPolygon.levels,
       				opacity:0.3,
       				weight:1,
       				numLevels:4,
       				zoomFactor: 4
       			}],  
       			fill:true,  color:originalColor,  opacity:polygonOpacity,  outline: polygonOutline
       		});
       		GEvent.addListener(polygon,'mouseover', PolygonHandlers.mouseOver );
       		GEvent.addListener(polygon,'mouseout', PolygonHandlers.mouseOut );
       		
       		polygon.id = boundary.id;
       		polygon.geo = {name: boundary.geoName};
       		if ( stats ) {
       			polygon.geo.heatMap = { values:  stats.values[i], valueLabels: stats.valueLabels };
       			//console.log( "name " + polygon.geo.name + " stat " + polygon.geo.stat + " color " + originalColor )
       		}
       		
       		totalPoints = totalPoints + inputPolygon.levels.length;
            ourPolygons.push(polygon);

           }
       }
   }
   searchControl.neighborhoodPolyGons = ourPolygons;
   enterTime = new Date().getTime()-enterTime;
   if ( RENDER.showStatistics ) {
	   var stats1 = "COUNT pts " + totalPoints + ", poly " + ourPolygons.length + ", TIMES remove " +  this.displayGeoState.removeTime + ", other " + (enterTime  - totalAO) + ", all " + enterTime;
	   GLog.write(stats1,'green');
   } else {
   }
	//alert(stats);
	this.displayGeoState.addOverlayTime = new Date().getTime();
	mapControl.addPolygons();
};

com.foreclosureagency.MapController.prototype.addPolygons = function () {
    var map = searchControl.mainMap;
	for( var i=0; i<90; i++ ) {
		if ( this.displayGeoState.index >= searchControl.neighborhoodPolyGons.length ) {
			if ( RENDER.showStatistics ) {
				GLog.write("Map addOverlay " + (new Date().getTime()-this.displayGeoState.addOverlayTime),"green");
			}
			return;
		}
		var p = searchControl.neighborhoodPolyGons[this.displayGeoState.index];
		map.addOverlay(p);
		this.displayGeoState.index++;
	}
	setTimeout("mapControl.addPolygons()",20);
}
/**
 * Fetch the listing/auction detail.
 */
com.foreclosureagency.MapController.prototype.showDetail=function(listingId,entityType) {
	var url = ACTION.detail[entityType.toLowerCase()];
	this.lastDetail = { id: listingId, entityType: entityType };
    searchControl.selectSubTab("detailPane");
	Public.progressIndicator.show();
    dojo.xhrPost(  {
        url: url,
        handleAs:"text",
        content:{id:listingId,random:new Date().valueOf(), entityType: entityType},
        me: this,
        load: function(response, ioArgs) {
        	var me = ioArgs.args.me;
        	me.showDetailHandler(response);
        },
        error: showError
    });
};

com.foreclosureagency.MapController.prototype.closeDetail=function() {
	listingDetailDialog.hide();
	if ( this.lastDetail  ) {
		if ( this.lastDetail.id ) {
    	    this.map.setMapType(G_NORMAL_MAP);
			searchControl.showListing(this.lastDetail.id, this.lastDetail.entityType );
		}
		if ( this.lastDetail.panorama ) {
			this.lastDetail.panorama.remove();
			this.lastDetail.panorama = null;
		}
		if ( this.lastDetail.satelliteMap ) {
			this.lastDetail.satelliteMap = null;
		}
		this.lastDetail = {};
	}
};

com.foreclosureagency.MapController.prototype.hookup = function() {
    if ( this.mapListeners && this.mapListeners.length ) {
        return;
    }
    var l = GEvent.addListener(this.map,'zoomend', dojo.hitch( this, this.mapZoomEndHandler) );
    this.mapListeners.push( l );

    l = GEvent.addListener(this.map,'moveend',dojo.hitch( this, this.mapMoveEndHandler ));
    this.mapListeners.push( l );

    l = GEvent.addListener(this.map,'dragend',dojo.hitch(this,this.mapDragEndHandler));
    this.mapListeners.push( l );

    l = GEvent.addListener( this.map, 'infowindowclose', function() {
    	searchControl.resetFeaturedListing();
    });
    this.mapListeners.push( l );
}

com.foreclosureagency.MapController.prototype.unhook = function() {
    for (var i=0; i < this.mapListeners.length; i++) {
        GEvent.removeListener(this.mapListeners[i]);
    };
    this.mapListeners = [];
}

/**
 * Create and intialize the map.
 */
com.foreclosureagency.MapController.prototype.createMap = function (mapDivId,startZoom,center) {
    this.initIcons();
    
    var mapDiv = dojo.byId(mapDivId);

    if ( !GBrowserIsCompatible() || mapDiv === null ) {
        return;
    }
    var latLng = new GLatLng( center.lat, center.lon );

    dojo.subscribe('rememberZoom', this, this.rememberZoom );
    
    this.map = new GMap2(mapDiv);
    this.map.addMapType(G_PHYSICAL_MAP);
    this.map.setMapType(G_PHYSICAL_MAP);
    this.map.setCenter(latLng, startZoom);
    
    this.clusterer = new Clusterer(this.map);
    this.clusterer.SetMaxVisibleMarkers( 100 );
    this.clusterer.SetMaxLinesPerInfoBox( 10 );
    
    var clusterIcon = this.createIcon('/web/images/house-multiples.png');
    this.clusterer.SetIcon(clusterIcon);
    
    clusterIcon = this.createIcon('/web/images/map/spotlight-cluster.png');
    this.clusterer.SetBestIcon(clusterIcon);
    
    this.hookup();
    
    this.faMapControl = new FAMapControl(this);
    this.map.addControl(this.faMapControl);
    this.map.addControl(new GMapTypeControl(), new GControlPosition( G_ANCHOR_TOP_RIGHT, GSize.ZERO));
    this.map.addControl(new GScaleControl());
    this.rememberZoomControl = new RememberZoomControl(this); 
    this.map.addControl(this.rememberZoomControl);

    this.existingMarkers=[];
    setTimeout("moveMapTypeLower()", 100 );
    return this.map;
};

var moveMapTypeLower = function() {
    dojo.query(".gmnoprint").forEach(function(a){
        if ( a.style.top == "0px" ) {
            a.style.top = "50px";
        }
    });
}


com.foreclosureagency.MapController.prototype.showListingsInZip = function(zip) {
	searchControl.fetchNewListingsForZipCode(zip);
	searchControl.selectSubTab("listingPane");	
};

com.foreclosureagency.MapController.prototype.updateMarkers=function (inputCluster) {
	var enterTime = new Date().getTime();
    var mapBounds = this.map.getBounds(),zoom=this.map.getZoom();
    this.clusterer.RemoveAllMarkers();
    
    if ( !inputCluster ) {
    	return;
    }
    inputCluster.filter( this , 'filtered', 'marker', function( obj, listings) {
    	
    		var out = [];
    		for( var i=0;i<listings.length;i++ ) {
    			var listing = listings[i];
                var latlng = new GLatLng(listing.lat,listing.lon);
    			var marker = obj.createMarker(listing, listing.markerType, this.map , latlng, zoom );	
    			
    			out.push(marker);
    		}
    		return out;
    	} );
            
    
    this.clusterer.geoCluster = inputCluster;
    this.clusterer.DisplayLater();
    if ( RENDER.showStatistics ) {
        enterTime = new Date().getTime()-enterTime;
    	GLog.write("update markers TIME: " + enterTime + " zoom " + zoom);
    }

};




var mapControl = new com.foreclosureagency.MapController();

