dojo.require('dojo.number');
dojo.require('dojo.currency');
dojo.require('dojo.string');
dojo.require("dojox.fx.easing");

/**
 * The minimum resolution to use in google maps.
 * 
 * @return
 */
function minimumResolution() {
	return (/msie/i.test(navigator.userAgent) && !/opera/i
			.test(navigator.userAgent)) ? RENDER.minZ + 1 : RENDER.minZ;
}

if ( typeof wlog == "undefined" ) {
    wlog = function(a) { if (console&&console.log){console.log(a);}};
}


dojo.declare("com.foreclosureagency.SearchController",null,{

		initialized : false,
		addresses : null,
		selectedAddress : null,
		searchState : null,
		searchStr : '',
		radius : null,
		mainMap : null,
		defaultZoom : (/msie/i.test(navigator.userAgent) && !/opera/i
				.test(navigator.userAgent)) ? 13 : 13,
		displayListingsZoomLimit : 10,
		messageStatus : {
			messageCount : 0,
			radius : 0
		},
		googleGeocoder : new GClientGeocoder(),
		mapVisible : true, // if the map is visible or not
		filters : {
			rad : 20,
			bed : [],
			type : [],
			bath : [],
			withoutPictures : true
		},
		OBRefresh : {
			homeValues : true,
			communityInfo : true,
			schools : true,
			attractions : true
		},

		// Received AJAX Items
		listings : null, // SUBSET OF filtered for the given map
		// viewport
		clustered : null, // Clustered data returned from the
		// server
		neighborhoods : null, // Neighborhood objects with TEXT
		// Geometry
		center : null, // Center of Map > center of searchStr (Zip)
		featuredListingId : null, // from an email
		featuredEntityType : null,
		noFeaturedListingDetail : false, // generally we show the
		// detail popup, this
		// variable inhibits that
		featuredZoom : 17, // zoom to use then clicking on a link
		// from email
		savedSearchId : null, // optional ID of the saved search being displayed
		lastOverlayBounds : null, // save the bounds when displaying the last
		// neighborhood/zip/county polygons
		lastListingBounds : null, // save the map bounds when we
		// last displayed listings
		boundaryType : 'ForeclosureCount', // the type of boundary to display
		boundaryTitle : 'Foreclosures', // the title to display in the legend
		prefetchBorder : 0, // how much to extend the search on
		// each area
		actionQueue : [], // when you need to chain different
		// actions just put them here
		communityDetailTimer : null,

		constructor : function(_searchStr, _zoomLevel, _center,
				_featuredListingId) {
			this.searchStr = _searchStr;
			if (_center) {
				this.center = _center;
			} else {
				this.center = {
					lat : 34,
					lon : -118
				};
			}
			if (_zoomLevel !== null && _zoomLevel > 14) {
				this.defaultZoom = _zoomLevel;
			}
			this.featuredListingId = _featuredListingId;

		},

		dequeueActions : function() {
			while (this.actionQueue.length > 0) {
				var action = this.actionQueue.shift();
				action.call(this);
			}
		},

		queueAction : function(f) {
			this.actionQueue.push(f);
		},

		showListing : function(id, entityType) {
			if (!dojo.byId("mainTabContainer")) {
				// allow this code to be reused outside the tab container
				return;
			}
			this.featuredEntityType = entityType;
			this.featuredListingId = id;
			this.noFeaturedListingDetail = true;
			if (!this.mapVisible) {
				this.selectSubTab('mapPane');
				// assume we are coming from the listingPane
				mapControl.mapHistory.push( {
					tab : 'listingPane',
					page : renderControl.currentPage
				});
			} else {
				this.doCenteredSearch();
			}
		},

		resetFeaturedListing : function() {
			this.featuredEntityType = null;
			this.featuredListingId = null;
			this.noFeaturedListingDetail = false;
			this.savedSearchId = null;
		},



		/**
		 * Either run the function if we have been fully initialized or save it for after the initialization.
		 */
		addOnLoad : function(foo) {
			if (this.mainMap) {
				foo.call(this);
			} else {
				this.queueAction(foo);
			}
		},

		/**
		 * The map has just been displayed.
		 */
		onMapShown : function() {
			this.mapVisible = true;
			this.mainMap.checkResize();
			var mapBounds = new GeoFetchParams();
			mapBounds.initFromMap(this.mainMap, 0);
			if (this.clustered
					&& this.lastListingBounds
					&& this.lastListingBounds
							.containsBounds(mapBounds)) {
				this.applyFilters(mapBounds.zoom);
			} else {
				this.lastListingBounds = null;
				if (this.featuredListingId) {
					this.doCenteredSearch();
				} else {
					this.doSearch(true);
				}
			}
		},

		/**
		 * The user moved the map as opposed to code changes to the center and zoom.
		 */
		onMapMovedByUser : function(bounds, zoom) {
			if (this.savedSearchId) {
				this.savedSearchId = null;
				this.lastListingBounds = null;
				this.handleNewView(bounds, zoom);
			}
		},

		/**
		 * An address was selected from the dropdown with multiple
		 * addresses.
		 */
		onAddressSelected : function(a) {
			var aOpt = a.target;
			var aIndex = aOpt.options[aOpt.selectedIndex].value;
			var address = this.addresses[aIndex];
			this.selectedAddress = address;
			var zoom = 14;
			if (address.accuracy) {
				zoom = this
						.computeZoomForAccuracy(address.accuracy);
			}
			this.moveMapToSelectedAddress(zoom);
		},

		updateHomeValues : function() {
			if (this.OBRefresh.homeValues) {
				this.updateOnBoard(dojo.byId('homeValuesPane'), 4);
				this.OBRefresh.homeValues = false;
			}
		},

		updateCommunityValues : function() {
			if (this.OBRefresh.communityInfo) {
				this.updateOnBoard(dojo.byId('communityInfoPane'),
						1);
				this.OBRefresh.communityInfo = false;
			}
		},

		updateSchools : function() {
			if (this.OBRefresh.schools) {
				this.updateOnBoard(dojo.byId('schoolsPane'), 2);
				this.OBRefresh.schools = false;
			}
		},

		updateAttractions : function() {
			if (this.OBRefresh.attractions) {
				this.updateOnBoard(dojo.byId('attractionPane'), 3);
				this.OBRefresh.attractions = false;
			}
		},

		updateOnBoard : function(contentPane, dataType) {
			var url = [], ui = 0;
			url[ui++] = 'http://www.onboardnavigator.com/webcontent/OBWC_Results.aspx?AID=573-b34cfeb36885';
			url[ui++] = '&datatype=';
			url[ui++] = dataType;
			url[ui++] = '&state=';
			url[ui++] = this.selectedAddress.state;
			url[ui++] = '&zip=';
			url[ui++] = this.selectedAddress.zip;
			url[ui++] = '&city=';
			url[ui++] = this.selectedAddress.city;
			var fullsrc = url.join('');
									
			contentPane.innerHTML='<iframe src="' + fullsrc + '" marginheight="0" marginwidth="0" width="100%" height="100%" ></iframe>';
		},

		/**
		 * Called from the UI to handle a new search.
		 */
		searchAddress : function() {
			// this func
			var newSearchStr = this.getSearchAddressElement().value;
			this.clustered = null;
			this.lastListingBounds = null;

			if (newSearchStr === null || newSearchStr === '') {
			    /* addressDialog.show(); */
			    showError("Please enter an address.");
			    this.getSearchAddressElement().focus();
				return;
			}

			if (this.searchStr != newSearchStr) {
				this.OBRefresh.homeValues = true;
				this.OBRefresh.communityInfo = true;
				this.OBRefresh.schools = true;
				this.OBRefresh.attractions = true;
			}
			this.searchStr = newSearchStr;
			this.resetFeaturedListing();
			this.doSearch();
		},

		handleGoogleAddresses : function(ga) {
			if (!ga.Status || ga.Status.code != 200) {
				this.showSearchInvalid();
				return;
			}
			var addresses = [];
			for ( var i = 0; i < ga.Placemark.length; i++) {
				var one = ga.Placemark[i];
				var address = {
					lon : one.Point.coordinates[0],
					lat : one.Point.coordinates[1]
				};
				if (typeof one.AddressDetails == "object") {
					address.accuracy = one.AddressDetails.Accuracy;
					if (one.AddressDetails.Country.CountryName == "USA"
							&& one.AddressDetails.Country.AdministrativeArea) {
						var aa = one.AddressDetails.Country.AdministrativeArea;
						if (aa.AdministrativeAreaName) {
							address.state = aa.AdministrativeAreaName;
							if (aa.Locality) {
								address.city = aa.Locality.LocalityName;
								if (aa.Locality.PostalCode) {
									address.zip = aa.Locality.PostalCode.PostalCodeNumber;
								}
								if (aa.Locality.Thoroughfare) {
									address.address = aa.Locality.Thoroughfare.Name;
								}
							}
							if (!address.city) {
								if ( typeof aa.SubAdministrativeArea != "undefined" ) {
									address.city = aa.SubAdministrativeArea.SubAdministrativeAreaName;
								}
							}
						}
					}
				}
				if (address.lon < 0) {
					addresses.push(address);
				}
			}
			var data = {
				center : {
					latitude : ga.Placemark[0].Point.coordinates[1],
					longitude : ga.Placemark[0].Point.coordinates[0]
				},
				addresses : addresses
			};
			// now fetch just the closest listing
			var that = this;
			dojo.xhrPost( {
						url : ACTION.search.address,
						content : {
							centerLongitude : data.center.longitude,
							centerLatitude : data.center.latitude
						},
						handleAs : "json-comment-filtered",
						load : function(rem, ioArgs) {
							rem.addresses = data.addresses;
							rem.center = data.center;
							that.handleSearchResults(rem, that.defaultZoom);
						},
						error : function(a, b) {
							showError(a, b, '[454]');
						}
					});
		},

		doSearch : function() {
			//set the mapPane into lastSelectSubTab variable
			if ( typeof parent.selectSubTabs == "undefined" ) {
				parent.selectSubTabs = new Array();
				parent.selectSubTabs[parent.selectSubTabs.length] = "mapPane";
			}
			
			this.displaySearchAddress(this.searchStr);
			// check to see if this is a webid
			isWebId = parseInt(this.searchStr)>99999;
			if ( isWebId) {
				window.location = "/web/search.do?searchAddress=" + parseInt(this.searchStr)
				return;
			}
			if (this.savedSearchId == null && !isWebId) {
				// look for addresses in the client
				this.googleGeocoder
						.getLocations(this.searchStr, dojo.hitch(
								this, this.handleGoogleAddresses));
			} else {
				var that = this;
				dojo.xhrPost( {
					url : ACTION.search.address,
					content : {
						savedSearchId : this.savedSearchId,
						id: this.searchStr
					},
					handleAs : "json-comment-filtered",
					load : function(data, ioArgs) {
						that.handleSearchResults(data,
								that.defaultZoom);
					},
					error : function(a, b) {
						showError(a, b, '[474]');
					}
				});
			}
		},

		doCenteredSearch : function() {
			var content = {
				id : this.featuredListingId
			};
			if (this.featuredEntityType) {
				content.entityType = this.featuredEntityType;
			}
			var that = this;
			dojo.xhrPost( {
				url : ACTION.search.listing,
				content : content,
				handleAs : "json-comment-filtered",
				load : function(data, ioArgs) {
					dojo.publish('rememberZoom', []);
					that.handleSearchResults(data,
							that.featuredZoom);
				},
				error : function(a, b) {
					showError(a, b, '[366]');
				}
			});
		},

		formatAddress : function(one) {

			var display = [], di = 0;
			if (one.address && one.address.length
					&& one.address.length > 2) {
				display[di++] = one.address;
				display[di++] = ", ";
			}
			if (one.city) {
				display[di++] = one.city;
				display[di++] = ", ";
			}
			if (one.county) {
				display[di++] = one.county;
				display[di++] = " County, ";
			}
			if (one.state) {
				display[di++] = one.state;
				display[di++] = " ";
			}
			if (one.zip) {
				display[di++] = one.zip;
			}
			return display.join('');
		},

		computeZoomForAccuracy : function(accuracy) {
			if (!accuracy) {
				return this.defaultZoom;
			}
			switch (this.selectedAddress.accuracy) {
			case 'ADDRESS':
			case 8:
				zoom = this.mainMap.getCurrentMapType()
						.getMaximumResolution();
				break;
			case 'INTERSECTION':
			case 'STREET':
			case 6:
			case 7:
				zoom = 16;
				break;
			case 'ZIP':
			case 5:
				zoom = 12;
				break;
			case 'TOWN':
			case 4:
				zoom = 10;
				break;
			}
			// c_onsole.log("computeZoomForAccuracy -> " + zoom );
			return zoom;
		},

		/**
		 * Fetch the form element that holds the address, support both FA and HX formats.
		 */
		getSearchAddressElement : function() {
			var txt = document.forms.searchForm.elements.searchAddress;
			if (!txt) {
				txt = document.forms.searchForm2.elements.searchAddress;
			}
			return txt;
		},

		displaySearchAddress : function(address) {
			this.getSearchAddressElement().value = address;
			var quickAddress = document.forms.quickForm
					&& document.forms.quickForm.elements.searchAddress;
			if (quickAddress) {
				quickAddress.value = address;
			}
		},

		moveMapToSelectedAddress : function(zoom) {
			var addressAsText = this
					.formatAddress(this.selectedAddress);
			this.displaySearchAddress(addressAsText);
			this.center = {
				lat : this.selectedAddress.lat,
				lon : this.selectedAddress.lon
			};
			var gltln = new GLatLng(this.center.lat,
					this.center.lon);
			try {
				this.mainMap.setCenter(gltln, zoom);
			} catch (e) {
				//alert( "Exception message " + e.message + " description " + e.description );
				// alert( 'moveMapToS 70, zoom ' + zoom + " lat " +
				// this.center.lat + " lon " + this.center.lon );
			}
		},

		showSearchInvalid : function() {
			var searchTerm = document.getElementById('searchAddress').value;
			if (!searchTerm) {
				return;
			}
			showError( "Could not find the address '" + searchTerm + "'" );
            document.getElementById('searchAddress').focus();
		},

		applyEntityType : function(result) {
			if (this.filters.entityType === null
					|| !this.filters.entityType.length) {
				return result;
			}

			var out = [];

			for ( var r = 0; r < result.length; r++) {
				var aMls = result[r];
				var existing = aMls.entityType == 'Auction' ? 'auc'
						: (!aMls.saleType ? 'reo' : aMls.saleType
								.toLowerCase());
				if (this.filters.precompEntityType[existing]) {
					out.push(aMls);
				}
			}
			//console.log('applyEntityType in:' + result.length + 'out:' + out.length);
			return out;
		},

		applyType : function(result) {
			if (this.filters.type === null
					|| !this.filters.type.length) {
				return result;
			}

			var len = this.filters.type.length;
			var out = [];

			var values = [];
			for ( var ft = 0; ft < this.filters.type.length; ft++) {
				values.push(com.foreclosure.homeTypes[this.filters.type[ft].value][1]);
			}
			for ( var r = 0; r < result.length; r++) {
				var aMls = result[r];
				var hasFilterChecked = false;
				var hasSpecificFilter = false;
				var isOtherChecked = false;

				if (aMls.entityType == 'Auction') {
					out.push(aMls);
					continue;
				}

				for ( var ty = 0; ty < len; ty++) {
					// first see if any of the filters match this
					// entry
					if (aMls.propertyType) {
						hasSpecificFilter = values[ty]
								.indexOf(aMls.propertyType
										.toLowerCase()) >= 0;
					}

					if (values[ty] == "other") {
						// decode the value of 'other' for later
						isOtherChecked = this.filters.type[ty].checked;
					}

					if (!hasSpecificFilter) {
						continue;
					}
					hasFilterChecked = this.filters.type[ty].checked;
					break;
				}
				var shouldKeep;
				if (!hasSpecificFilter) {
					shouldKeep = isOtherChecked;
				} else {
					shouldKeep = hasFilterChecked;
				}

				if (shouldKeep) {
					out.push(aMls);
				}
			}
			//console.log('applyType in:' + result.length + 'out:' + out.length);
			return out;
		},

		applyBed : function(result) {
			if (this.filters.bed === null
					|| this.filters.bed.value == -1) {
				return result;
			}

			var value = parseInt(this.filters.bed.value);

			var out = [];
			for ( var r = 0; r < result.length; r++) {
				var aMls = result[r];

				if ( value == aMls.bedrooms
						|| ( value == 3 && (aMls.bedrooms >= 3
								|| aMls.bedrooms === null || aMls.bedrooms === 0.0))) {
					out.push(aMls);
				}
			}
			return out;
		},

		applyBath : function(result) {
			if (this.filters.bath === null
					|| this.filters.bath.value == -1 ) {
				return result;
			}

			var value = parseInt(this.filters.bath.value);

			var out = [];
			for ( var r = 0; r < result.length; r++) {
				var aMls = result[r];

				// check earlier for possible null or end of
				// range
				if ((aMls.bathrooms >= 3
						|| aMls.bathrooms === null || aMls.bathrooms === 0)) {
					if (value == 3) {
						out.push(aMls);
					}
					continue;
				}
				// compare with possible fractional bath
				var diffBath = aMls.bathrooms - value;
				if (0 <= diffBath && diffBath < 1.0 ) {
					out.push(aMls);
				}
			}
			// c_onsole.log('applyBath in:' + result.length + '
			// out:' + out.length);
			return out;
		},

		applySqFt : function(result) {
			var out = [];
			var value = parseInt(this.filters.sqFt.minSq)
			for ( var r = 0; r < result.length; r++) {
				var aMls = result[r];
				if (aMls.entityType == 'Auction') {
					out.push(aMls);
					continue;
				}

				if (!aMls.size || aMls.size === 0) {
					out.push(aMls);
				} else if (aMls.size >= value ) {
					out.push(aMls);
				}
			}
			//console.log('applySqFt in:' + result.length + 'out:' + out.length);
			return out;

		},

		applyWithoutPictures : function(result) {
			if (this.filters.withoutPictures == true) {
				return result;
			}
			var out = [];
			for ( var r = 0; r < result.length; r++) {
				var aMls = result[r];
				if (aMls.photoURL.indexOf('/web/pictures/sample') == -1) {
					out.push(aMls);
				}
			}
			// c_onsole.log('applySqFt in:' + result.length + '
			// out:' + out.length);
			return out;

		},

	fetchListing : {
		correlation : 0,
		inFlight : 0
	},

	fetchNeighborhood : {
		correlation : 0
	}

});

com.foreclosureagency.SearchController.prototype.openOnboard = function(data) {
	var url=[],i=0;
	url[i++] = 'http://www.onboardnavigator.com/webcontent/OBWC_Results.aspx?AID=573-b34cfeb36885&datatype=';
	url[i++] = data;
	url[i++] = '&state=';
	url[i++] = this.selectedAddress.state;
	url[i++] = '&zip=';
	url[i++] = this.selectedAddress.zip;
	url[i++] = '&city=';
	url[i++] = this.selectedAddress.city;
	window.open( url.join(''),'Info','scrollbars=yes,width=640,height=500');	
};
						
com.foreclosureagency.SearchController.prototype.initFormFromUrl = function() {
	var parms = GeoLib.parseParams();

	var frm = document.forms.searchForm;

	if (parms.bedrooms && parms.bedrooms > -1) {
		var bedrooms = frm.elements.bedrooms;
		for ( var b = 0; b < bedrooms.length; b++) {
			bedrooms[b].checked = b >= parms.bedrooms;
		}
	}
	// frm.elements.homeType;
	if (parms.bathrooms && parms.bathrooms > 0) {
		var bathrooms = frm.elements.bathrooms;
		for (b = 0; b < bathrooms.length; b++) {
			bathrooms[b].checked = (b + 1) >= parms.bathrooms;
		}
	}
	if (parms.sqFtMin) {
		frm.elements.sqFtMin.value = parms.sqFtMin != -1 ? parms.sqFtMin
				: '';
	}
	if (parms.homeType) {
		// the api to decode will send one value if just one parameter, array otherwise
		// normalize to array here
		if (!parms.homeType.length) {
			parms.homeType = [ parms.homeType ];
		}
		for (hi = 0; hi < frm.elements.homeType.length; hi++) {
			var el = frm.elements.homeType[hi];
			el.checked = false;
			for ( var hj = 0; hj < parms.homeType.length; hj++) {
				if (el.value == parms.homeType[hj]) {
					el.checked = true;
					break;
				}
			}
		}
	}
	if (parms.id) {
		this.featuredListingId = parms.id;
	}
	if (parms.entityType) {
		this.featuredEntityType = parms.entityType;
	}
	if (parms.noDetail) {
		this.noFeaturedListingDetail = true;
	} else {
		this.noFeaturedListingDetail = false;
	}
	if (parms.radius) {
		this.radius = parms.radius;
	}

	if (parms.searchAddress) {
		this.searchStr = unescape(parms.searchAddress);
		if ( this.searchStr.indexOf("?searchAddress=")==0) {
			this.searchStr = this.searchStr.substring(15);
		}
		this.displaySearchAddress(this.searchStr);
	}

	if (parms.savedSearchId) {
		this.savedSearchId = parms.savedSearchId;
	} else {
		this.savedSearchId = null;
	}

};

						
com.foreclosureagency.SearchController.prototype.onLoad = function() {
	var invalid = false;
	if (this.center === null) {
		this.center = {
			lat : 37.769055,
			lon : -122.445968
		}; // hmm a default center?
		invalid = true;
	}
	this.mainMap = mapControl.createMap("map_view",
			this.defaultZoom, this.center);

	// connect the menu
	var that = this;
	var boundarySelect = dojo.query('[name="boundarySelect"]');
	if (boundarySelect) {
		boundarySelect.onclick( function(evt) {
			that.boundarySelectionChanged(evt.target.form);
		});
	}
	
	var commentsButton = dojo.query(".view-comments");
	if ( commentsButton ) {
		commentsButton.onclick( function(evt) {
			that.showComments();
		});
		
	}
	
	var savedSearchLink = dojo.query(".save-button a");
	if ( savedSearchLink ) {
	    savedSearchLink.onclick( function(evt){
	        var zip = that.getSearchAddressElement().value;
	        if ( zip) {
	        	zip = zip.replace(/[^0-9]/g," ").split(" ");
	        	if ( zip && zip.length ) 
	        		zip = zip[zip.length-1];
	        }
	        (dojo.query("input[name='zipcode']")[0]).value = zip;
	        saveSearchDialog.show();           
	    });
	}

	// parse any passed in parameters and setup the form
	this.initFormFromUrl();

	// do not do the rest of the initialization if there is
	// a hash and it is not ours
	if (!GeoLib.isPanelActivated('map')) {
		this.dequeueActions();
		return;
	}
	this.mapVisible = true;

	if (this.featuredListingId) {
		if (this.noFeaturedListingDetail) {
			this.doCenteredSearch();
		} else {
			mapControl.showDetail(this.featuredListingId,
					'Listing');
			this.queueAction(this.doCenteredSearch);
		}
		this.queueAction( function() {
					that.boundarySelectionChanged(document.forms.boundaryForm);
				});
		return;
	} else {
		this.doSearch(true);
	}

	if (invalid) {
		this.showSearchInvalid();
	}

	this.boundarySelectionChanged(document.forms.boundaryForm);

	// run code if we have been asked to do so
	this.dequeueActions();
};


com.foreclosureagency.SearchController.prototype.applyFilters = function(zoom) {
    if ( !zoom ) {
        zoom = this.mainMap.getZoom();
    }
	var frm = document.forms.searchForm;
	this.filters.bed = frm.elements.bedrooms;
	this.filters.type = frm.elements.homeType;
	this.filters.bath = frm.elements.bathrooms;
	this.filters.entityType = frm.elements.entityType;
	if (document.listingPictures) {
		this.filters.withoutPictures = document.listingPictures.withoutPictures.checked;
	} else {
		this.filters.withoutPictures = true;
	}
	var minSq = frm.elements.sqFtMin.value;
	if (minSq == -1) {
		this.filters.sqFt = null;
	} else {
		this.filters.sqFt = {
			minSq : minSq
		};
	}
	
	// precompile entityType filters
	var len = this.filters.entityType.length;
	this.filters.precompEntityType = {};
	for ( var ty = 0; ty < len; ty++) {
		var entityType = this.filters.entityType[ty];
		this.filters.precompEntityType[entityType.value] = entityType.checked;
	}

	

	this.listings = [];
	// Apply the filters and store the data back inside the
	// cluster
	if (this.clustered) {
		this.clustered.resetMinPriced();
		this.clustered.filter(this, undefined, 'filtered',
				function(obj, listings) {
					var result = listings;
					if (obj.filters.type !== null) {
						result = obj.applyType(result);
					}
					if (obj.filters.bed !== null) {
						result = obj.applyBed(result);
					}
					if (obj.filters.bath !== null) {
						result = obj.applyBath(result);
					}
					if (obj.filters.sqFt !== null) {
						result = obj.applySqFt(result);
					}
					if (obj.filters.entityType !== null) {
						result = obj.applyEntityType(result);
					}
					if (obj.filters.withoutPictures !== null) {
						result = obj
								.applyWithoutPictures(result);
					}
					obj.clustered.trackMinPriced(result);

					// track the list of all the listings
				// for other parts of the code
				obj.listings = obj.listings.concat(result);
				return result;

			});
		if (this.clustered.minPriced) {
			this.clustered.minPriced.markerType = 'best';
		}
	}

	this.updateMap(zoom);
	dojo.publish('filterChanged');

};

						
/**
 * Handle the clicking of the property count/title.
 */
com.foreclosureagency.SearchController.prototype.onPropertiesCountClicked = function() {
	if (this.listings != null && this.listings.length > 0) {
		this.selectSubTab("listingPane");
	} else {
		try {
			this.mainMap.zoomIn();
		} catch (e) {
		}
	}
};

/**
 * Notify the controller that the user selected a new value for the boundary.
 */
com.foreclosureagency.SearchController.prototype.boundarySelectionChanged = function( formEl ) {
	var sel = formEl && formEl.boundarySelect;
	if ( !sel ) {
		return;
	}
	var el = sel.options[sel.selectedIndex];
	if ( el.value == "on" ) {
	    return;
	}
	this.boundaryType = el.value;
	this.boundaryTitle = el.text;
	this.boundaryTitle = this.boundaryTitle.replace(/^\s\s*/, '').replace(
			/\s\s*$/, '')
	this.viewOnMap();
};

com.foreclosureagency.SearchController.prototype.updateMap = function(zoom) {
	var shown = this.listings;

	var msg = [], d = 0;
	msg[d++] = "<span class='hud'>";
	msg[d++] = "<a id='zoomIn' href='#' onclick='searchControl.onPropertiesCountClicked()'>";
	if (shown !== null && shown.length > 0
			&& zoom > this.displayListingsZoomLimit) {
		msg[d++] = "Showing "
		msg[d++] = shown.length;
		msg[d++] = " properties ";
		if (this.clustered && (shown.length < this.clustered.numListings)) {
			msg[d++] = " out of ";
			msg[d++] = this.clustered.numListings;
			msg[d++] = " ";
		}
	} else if (this.clustered.numListings > 0) {
		msg[d++] = this.clustered.numListings;
		msg[d++] = " properties, zoom in for detail.";
	}
	msg[d++] = "</a>";
	if (RENDER.messageSummary) {
	    var nodeList  = dojo.query(".view-comments h5 strong");
	    if ( nodeList && nodeList.length && nodeList[0]) {
	        nodeList[0].innerHTML = this.messageStatus.messageCount;
        }
	}
	msg[d++] = "</span>";
	dojo.byId("mapCountId").innerHTML = msg.join('');

	if (this.mapVisible) {
		if (zoom > this.displayListingsZoomLimit) {
			mapControl.updateMarkers(this.clustered);
		} else {
			mapControl.updateMarkers(null);
		}
	}

};

com.foreclosureagency.SearchController.prototype.handleSearchResults = function(
		data, zoom) {
	this.initialized = true;
	this.addresses = data.addresses;
	this.selectedAddress = null;
	if (!data.addresses || !data.addresses.length) {
		this.showSearchInvalid();
		return;
	}

	var aOpt = document.getElementById('searchAddressOptions');
	var searchAddressDiv = document.getElementById('searchAddressDiv');
	var selectAddressDiv = document.getElementById('selectAddressDiv');
	if (data.addresses.length > 1) {
		searchAddressDiv.style.display = 'none';
		selectAddressDiv.style.display = 'inline';
		aOpt.style.display = 'block';
		aOpt.options.length = 0;
		aOpt.options[aOpt.options.length] = new Option('...', 0);
		for ( var ai = 0; ai < data.addresses.length; ai++) {
			var one = data.addresses[ai];
			aOpt.options[aOpt.options.length] = new Option(this.formatAddress(one), ai+1);
		}
	} else {
		searchAddressDiv.style.display = 'inline';
		selectAddressDiv.style.display = 'none';
		aOpt.style.display = 'none';
	}
	this.selectedAddress = this.addresses[0];
	if (!zoom) {
		zoom = this.computeZoomForAccuracy(this.selectedAddress.accuracy);
	}
	if (!this.selectedAddress || !this.selectedAddress.lat) {
		//addressDialog.show();
	} else {
		if (!this.mapVisible) {
			//c_onsole.log("the map is not visible, do not manipulate it" );
			this.fetchNewListings(this.selectedAddress);
			return;
		}
		// adjust the zoom level to make sure some listings are included
		if (data.closestListing && data.closestListing.lat) {
			var bounds = this.mainMap.getBounds();
			var closest = new GLatLng(data.closestListing.lat, data.closestListing.lon);
			if (!bounds.contains(closest)) {
				/*				
				 var dlat = Math.abs(this.selectedAddress.lat-data.closestListing.lat);
				 var dlon = Math.abs(this.selectedAddress.lon-data.closestListing.lon);
				 var sw = new GLatLng(this.selectedAddress.lat-dlat,this.selectedAddress.lon-dlon);
				 var ne = new GLatLng(this.selectedAddress.lat+dlat,this.selectedAddress.lon+dlon);
				 bounds = new GLatLngBounds(sw,ne);
				 var newzoom = this.mainMap.getBoundsZoomLevel(bounds);
				 if ( newzoom <minimumResolution() ) {
				 newzoom = minimumResolution();
				 }
				 if ( newzoom < zoom  ) {
				 var dbounds = bounds.toSpan();
				 // c_onsole.log("adjusting zoom from " + zoom + " to "+
					// newzoom + " visible " + this.mapVisible);
				 zoom = newzoom;
				 }
				 */
				this.selectedAddress.lat = data.closestListing.lat;
				this.selectedAddress.lon = data.closestListing.lon;
			}
		}
		this.moveMapToSelectedAddress(zoom);

	}
};

com.foreclosureagency.SearchController.prototype.onNewBoundaryInformation = function(
		response, xhr) {

	this.neighborhoods = response.neighborhoods;
	mapControl.removeExistingPolygons();
	// find the index of the active boundary type
	var activeIndex = 0;
	while (activeIndex < response.valueLabels.length) {
		if (response.valueLabels[activeIndex] == this.boundaryType) {
			break;
		}
		activeIndex++;
	}
	var heatMap = {
		values : response.values,
		activeIndex : activeIndex,
		valueLabels : response.valueLabels
	};
	var title = null;
	if (activeIndex < response.valueLabels.length) {
		title = this.boundaryTitle;
	}
	mapControl.geoOnMap(this.neighborhoods, heatMap, title,
			this.lastOverlayBounds.zoom);
	Public.progressIndicator.hide();
};
/**
 * Fetch and display neighborhood information for the current active bounds.
 */
com.foreclosureagency.SearchController.prototype.viewOnMap = function() {

	if (!this.boundaryType || this.boundaryType == 'none') {
		this.showNeighborhoods = false;
		mapControl.removeExistingPolygons();
		mapControl.geoOnMap( [], [], '', 17);
		return true;
	}
	this.showNeighborhoods = true;
	this.lastOverlayBounds = new GeoFetchParams();
	this.lastOverlayBounds.initFromMap(this.mainMap, this.prefetchBorder);
	var fb = this.lastOverlayBounds.content();
	fb.boundaryType = this.boundaryType;
	var that = this;
	Public.progressIndicator.show();
	this.fetchNeighborhood.correlation++;
	var args = {
		url : ACTION.neighborhood,
		content : fb,
		correlation : this.fetchNeighborhood.correlation,
		load : function(data, xhr) {
			if (that.fetchNeighborhood.correlation != xhr.args.correlation) {
				Public.progressIndicator.hide();
				return;
			}
			that.onNewBoundaryInformation(data, xhr);
		},
		handleAs : "json-comment-filtered",
		error : function(a, b) {
			showError(a, b, '[836]');
		}
	};
	var requestObj = dojo.xhrPost(args);
	return true;
};

/**
 * Fetch new listings after the map has been panned or zoomed out.
 */
com.foreclosureagency.SearchController.prototype.fetchNewListings = function(
		center) {
	this.lastListingBounds = new GeoFetchParams();
	if (center) {
		this.lastListingBounds.initFromCenter(center);
	} else {
		this.lastListingBounds.initFromMap(this.mainMap, 0);
	}
	var content = this.lastListingBounds.content();
	if (this.radius) {
		content.radius = this.radius;
	}
	if (this.savedSearchId) {
		content.savedSearchId = this.savedSearchId;
	}
	dojo.publish("addressChanged", [ this ]);
	this.fetchListing.correlation++;
	this.fetchListing.inFlight = 1;
	Public.progressIndicator.show();
	var args = {
		url : ACTION.listingInBoundary,
		content : content,
		load : dojo.hitch(this, this.onNewListingsAvailable),
		handleAs : "json-comment-filtered",
		correlation : this.fetchListing.correlation,
		error : function(a, b) {
			showError(a, b, '[795]');
		}
	};
	var requestObj = dojo.xhrPost(args);
};

com.foreclosureagency.SearchController.prototype.fetchNewListingsForZipCode = function(
		zip) {
	var bounds = new GeoFetchParams();
	bounds.initFromMap(this.mainMap, 0);
	var content = this.lastListingBounds.content();
	content.zip = zip;
	this.fetchListing.correlation++;
	this.fetchListing.inFlight = 1;
	Public.progressIndicator.show();
	var args = {
		url : ACTION.listingInBoundary,
		content : content,
		load : dojo.hitch(this, this.onNewListingsAvailable),
		handleAs : "json-comment-filtered",
		correlation : this.fetchListing.correlation,
		error : function(a, b) {
			showError(a, b, '[795]');
		}
	};
	var requestObj = dojo.xhrPost(args);
};

com.foreclosureagency.SearchController.prototype.handleNewView = function(
		nbounds, nzoom) {
	var dist_meter = nbounds.getSouthWest()
			.distanceFrom(nbounds.getNorthEast());
	var side = dist_meter / (1600 * 1.4142);
	// c_onsole.log( "zoom " + nzoom + " diagonal (meters) " + dist_meter + "
	// side (miles) " + side );
	// c_onsole.log('new view zoom ' + nzoom );
	PolygonHandlers.handleNewView();
	// check to see if we need new mlsdata
	if ((this.lastListingBounds === null)
			|| !this.lastListingBounds.containsBounds(nbounds)
			|| (this.lastListingBounds.zoom != nzoom)) {
		this.fetchNewListings();
	}
	/*
	if ((this.lastOverlayBounds === null)|| !this.lastOverlayBounds.containsBounds(nbounds)|| (this.lastOverlayBounds.zoom != nzoom)) {
		if (this.lastOverlayBounds !== null
				&& this.lastOverlayBounds.zoom != nzoom) {
			mapControl.removeExistingPolygons();
		}
		this.viewOnMap();
	}*/

};

/**
 * Process ajax data from the server.
 */
com.foreclosureagency.SearchController.prototype.onNewListingsAvailable = function(
		data, xhr) {
	if (this.fetchListing.correlation != xhr.args.correlation) {
		Public.progressIndicator.hide();
		return;
	}
	if (data.city) {
		var el = dojo.byId('cityStateId');
		var address = data.city + ", " + data.state + " " + data.zip;
		el.innerHTML = address;
		this.displaySearchAddress(address);
	}
	this.fetchListing.inFlight = 0;
	this.clustered = new GeoCluster();
	this.clustered.init(data.cluster);
	this.messageStatus = data.messageStatus;
	// c_onsole.log('new data, applyFilters() called');
	this.applyFilters(xhr.args.content.zoomLevel);
	this.viewOnMap();

	Public.progressIndicator.hide();
};

com.foreclosureagency.SearchController.prototype.selectTab = function(id) {
	var paneId = id + "Pane";
	var one = dojo.byId(paneId);
	if ( !one ) {
		if ( console && console.log) console.log("Cannot find the tab with id " + id);
		return;
	}
	// display the tab
	var tabs = dojo.query(".tabPanel");
	tabs.style('display','none');
	
	one.style.display = 'block';
	// activate the menu
	dojo.query("#fh-tabs .tabs li").removeClass('selected');
	dojo.addClass(id,'selected');
	
	if ( id == 'mapListing' ) {
		dojo.publish("mapPane/show");
		dojo.publish("listingPane/hide");		
		this.mapVisible = true;
		this.onMapShown();
	}  else {
		dojo.publish("mapPane/hide");
		dojo.publish("listingPane/hide");		
		this.mapVisible = false;
		if ( id == 'homeValues') {
			this.updateHomeValues();
		} else if ( id == 'communityInfo') {
			this.updateCommunityValues();
		} else if ( id == 'schools') {
			this.updateSchools();
		} else if ( id == 'attraction') {
			this.updateAttractions();
		} else if ( id == 'searchAddress') {
			this.onAddressSelected();
		} else  {
			if ( console && console.log ) console.log( "Did not match id " + id);
		}
	}
	dojo.byId("commentsButton").style.display=this.mapVisible?'inline':'none';	
};

com.foreclosureagency.SearchController.prototype.showComments = function() {
	dojo.byId("messagesPane").style.display='block';
	dojo.publish("messagesPane",[true]);
	window.scrollTo(0,500);
}

var safeNumber = function(a) {
	a = parseInt(a);
	if( isNaN(a) ) {
		a = -1;
	}
	return a;
}

com.foreclosureagency.SearchController.prototype.selectSubTab = function(subTabName) {
	if(subTabName != "goBackButton") {
		if((typeof parent.selectSubTabs != "undefined") && (subTabName.search("-back-") == -1)) {
			var newState = dojo.hitch(parent,"addStateToHistory", subTabName);
			newState();
		}
		
		if (subTabName.search("-back-") != -1) {
			subTabName = subTabName.replace("-back-", "");
		}
		
	} else {
		if(typeof parent.selectSubTabs != "undefined") {
			subTabName = parent.lastState();
		} else {
			history.go(-1);
		}
	}

    var panes = ["mapPane","listingPane","detailPane"];
    this.mapVisible = false;
    {
        // re-enable the menus for our panel.
        var menu = dojo.query("." + subTabName + "Dialog");
        console.dir(menu);
        menu.style('display','block');
    }
    for( var i=0; i<panes.length;i++) {
        var display = (subTabName==panes[i])?"block":"none";
        dojo.byId(panes[i]).style.display = display;
        if ( subTabName != panes[i] ) {
            var menu = dojo.query("." + panes[i] + "Dialog");
            for( var mi=0;mi<menu.length;mi++) {
                if( menu[mi].className.indexOf(subTabName)==-1 ) {
                    menu[mi].style.display = 'none';
                }
            }
        }
    }
    if ( subTabName == "mapPane"){
        var wasVisible = this.mapVisible;
		this.mapVisible = true;
		if ( !wasVisible ) {
		    this.onMapShown();
		}
	}
	dojo.byId("map-off").style.display=this.mapVisible?'none':'inline';
	dojo.byId("map-on").style.display=this.mapVisible?'inline':'none';
	dojo.byId("list-off").style.display=this.mapVisible?'inline':'none';
	dojo.byId("list-on").style.display=this.mapVisible?'none':'inline';
	dojo.publish("mapSubPane",[subTabName]);
};

com.foreclosureagency.SearchController.prototype.saveSearch = function() {
    var email = dojo.query("input[name='emailAddress']")[0].value;
    var zip = (dojo.query("input[name='zipcode']")[0]).value;
    var frm = document.forms.searchForm;
    var content = {
        'savedSearch.email': email,
        'savedSearch.priceMin':-1,
        'savedSearch.priceMax':-1,
        'savedSearch.zip':zip,
        'savedSearch.radius':10,
        'savedSearch.bedrooms': safeNumber(frm.bedrooms.options[frm.bedrooms.selectedIndex].value),
        'savedSearch.bathrooms':safeNumber(frm.bathrooms.options[frm.bathrooms.selectedIndex].value),
        'savedSearch.sqFtMin':safeNumber(frm.sqFtMin.options[frm.sqFtMin.selectedIndex].value),
        'savedSearch.sqFtMax':-1,
        'savedSearch.frequency':7      
    };
	var args = {
		url : '/web/ajax/savedSearches/createJson.do',
		content : content,
		load : function(){
		    savedSearch.needsFetch();
		    setTimeout( "savedSearch.activate()", 100 );
		},
		handleAs : "json-comment-filtered",
		error : function(a, b) {
			showError(a, b, '[1285]');
		}
	};
    saveSearchDialog.hide();
	dojo.xhrPost(args);

}


var searchControl = new com.foreclosureagency.SearchController();

dojo.addOnLoad( function(){
	//searchControl.selectTab('mapListing');
	dojo.query("#fh-tabs .tabs a").onclick(function(evt){
		searchControl.selectTab(evt.target.parentNode.id);
		dojo.stopEvent(evt);
	});
});

G_PHYSICAL_MAP.getMinimumResolution = minimumResolution;
G_NORMAL_MAP.getMinimumResolution = minimumResolution;
G_SATELLITE_MAP.getMinimumResolution = minimumResolution;
G_HYBRID_MAP.getMinimumResolution = minimumResolution;
