function MapSearch(options) {
	this.init(options);
}

$.extend(MapSearch.prototype, {
	form : null,
	mapCanvas : null,
	resultsContainer : null,
	popup : null,
	center : {'lat': -100.546864, 'lng': 9.795794},
	zoom : 1,
	restrictPolygon: false,
	polygonBounds: null,
	searchRequest : null,
	detailAjax : null,
	mapAjax : null,
	compare_properties : false,
	regionAjax : null,
	countAjax : null,
	markers : {},
	total : 0,
	page : 0,
	featuredHappened : false,
	redirectIfOneResult : false,
	keywordSearchHappened : false,
	priceRegex : /(\d+)(\d{3})/,
	status_tags : {
		1: '/images/site/tag_available.gif',
		2: '/images/site/tag_pending.gif',
		3: '/images/site/tag_contract.gif',
		4: '/images/site/tag_sold.gif',
		5: '/images/site/tag_leased.gif'
	},

	init : function(options) {
		if (options) {
			if (options.form) {
				this.form = $(options.form);
			} else {
				if (options.formId) {
					this.form = $('#'+options.formId);
				}
			}
			if (options.mapCanvas) {
				this.mapCanvas = options.mapCanvas;
			} else {
				if (options.mapCanvasId) {
					this.mapCanvas = document.getElementById(options.mapCanvasId);
				}
			}
			if (options.resultsContainer) {
				this.resultsContainer = $(options.resultsContainer);
			} else {
				if (options.resultsContainerId) {
					this.resultsContainer = $('#'+options.resultsContainerId);
				}
			}
			if (options.center) this.center = options.center;
			if (options.compare_properties) this.compare_properties = options.compare_properties;
			if (options.restrictPolygon) this.restrictPolygon = options.restrictPolygon;
			if (options.redirectIfOneResult) this.redirectIfOneResult = options.redirectIfOneResult;
			if (options.zoom) this.zoom = options.zoom;
			if (options.popup) {
				this.popup = options.popup;
			} else {
				this.popup = new IframePopup({'id': 'map-search-popup', 'title': 'Property Details'});
			}
		}
		
		this.render();
		
		var obj = this;
		this.form.submit(function() {
			return obj.search();
		});
	},
	
	render : function() {
    	if (GBrowserIsCompatible()) {
			var gmap = new GMap2(this.mapCanvas);
			gmap.setCenter(new GLatLng(this.center.lat, this.center.lng), this.zoom);
			gmap.addControl(new GLargeMapControl());
			gmap.addControl(new GMapTypeControl());
			//gmap.addControl(new GOverviewMapControl());
			
			this.gmap = gmap;
			
			$(document).unload(GUnload);
			
			this.markerIcon = new GIcon(G_DEFAULT_ICON);
			this.markerIcon.image = '/images/map/house.png';
			this.markerIcon.shadow = null;
			this.markerIcon.iconSize = new GSize(18, 18);
			this.markerIcon.iconAnchor = new GPoint(9, 9);

			this.maxOverlay = new GScreenOverlay('/images/map/map_max.png',
					  	new GScreenPoint(.5, .5,'fraction', 'fraction'),  // screenXY
						new GScreenPoint(80, 51),  // overlayXY
						new GScreenSize(160, 102)  // size on screen
					  ); 
			this.gmap.addOverlay(this.maxOverlay);
			this.maxOverlay.hide();
			
			this.loadBGOverlay = new GScreenOverlay('/images/map/map_progress.png',
					  	new GScreenPoint(.5, .5,'fraction', 'fraction'),  // screenXY
						new GScreenPoint(80, 51),  // overlayXY
						new GScreenSize(160, 102)  // size on screen
					  );  
			this.gmap.addOverlay(this.loadBGOverlay);
			this.loadBGOverlay.hide();
			
			this.loadingOverlay = new GScreenOverlay('/images/map/loading.gif',
					  	new GScreenPoint(.5, .5, 'fraction', 'fraction'),  // screenXY
						new GScreenPoint(16, 20),  // overlayXY
						new GScreenSize(32, 32)  // size on screen
					  );  
			this.gmap.addOverlay(this.loadingOverlay);
			this.loadingOverlay.hide();
			
			var obj = this;
			if (!this.restrictPolygon) {
				if (!this.form.find('#ignore_bounds').val()) {
					GEvent.addListener(this.gmap, 'moveend', function() {
						obj.doSearch();
						obj.form.find('#region').val('');
					});
				}
			}
			this.form.find('#min_price').change(function() {
				var p = obj.form.find('#min_price');
				p.val(p.val().replace(/[^0-9]/g, ''));
				obj.doSearch();
			});
			this.form.find('#max_price').change(function() {
				var p = obj.form.find('#max_price');
				p.val(p.val().replace(/[^0-9]/g, ''));
				obj.doSearch();
			});
			this.form.find('#bedrooms').change(function() { obj.doSearch(); });
			this.form.find('#bathrooms').change(function() { obj.doSearch(); });
			this.form.find('#has_video').change(function() { obj.doSearch(); });
			this.form.find('#listing_age').change(function() { obj.doSearch(); });
			this.form.find('input[name="category_id[]"]').change(function() { obj.doSearch(); });
			this.form.find('input[name="subcategory_id[]"]').change(function() { obj.doSearch(); });
			this.form.find('input[name="amenity[]"]').change(function() { obj.doSearch(); });
			this.form.find('input[name="include_mls"]').change(function() {
//				if (this.value) {
//					obj.form.find('input[name="municipality_id[]"]').attr('checked', false);
//				}
				obj.doSearch();
			});

			this.form.find('#zip_code').bind('keyup', function(e) {
				obj.form.find('.loc_type:not(.zip_code:checkbox)').val('');
				obj.form.find('.loc_type:checkbox:not(.zip_code)').attr('checked', false);
				obj.doSearch();
			});
			this.form.find('#region').change(function() {
				obj.form.find('.loc_type:not(.region:checkbox)').val('');
				obj.form.find('.loc_type:checkbox:not(.region)').attr('checked', false);
				obj.search();
			});
			this.form.find('#county_id').change(function() {
				obj.form.find('.loc_type:not(.county_id:checkbox)').val('');
				obj.form.find('.loc_type:checkbox:not(.county_id)').attr('checked', false);
				obj.doSearch();
			});
			this.form.find('#city').change(function() {
				obj.form.find('.loc_type:not(.city:checkbox)').val('');
				obj.form.find('.loc_type:checkbox:not(.city)').attr('checked', false);
				obj.doSearch();
			});
			this.form.find('input[name="municipality_id[]"]').change(function() {
//				obj.form.find('input[name="include_mls"]').attr('checked', false);
//				obj.form.find('#include_mls0').attr('checked', true);
				obj.form.find('.loc_type:not(.municipality_id:checkbox)').val('');
				obj.doSearch();
			});
    	}
	},
	
	search : function() {
		this.page = 0;
		
		if (this.form.find('input[name=featured]').val()) {
			if (!this.featuredHappened) {
				this.featuredHappened = true;
			} else {
				this.form.find('input[name=featured]').val(0);
			}
		}
		
		if (this.form.find('#region').val()) {
			this.getSearchRegion();
		} else {
			this.form.find('#search_region').val('');
			this.doSearch();
		}
		
		return false;
	},
	
	getSearchRegion : function() {
		var obj = this;
		if (this.regionAjax) {
			this.regionAjax.abort();
			this.regionAjax = null;
		}
		
		this.regionAjax = $.ajax({
			'type': 'POST',
			'url': '/listings/load-search-region',
			'data': {'search_region_id': $('#region').val()},
			'dataType': 'json',
			'success': function(data, status) {
				obj.parseSearchRegion(data);
				obj.doSearch();
			}
		});
	},
	
	parseSearchRegion: function(search_region) {
		var points = new Array();
		var point = null;
		var lineArray = null;
	    var lat = null;
	    var lng = null;
		var lines = search_region.data.split("\n");
		for (var i=0; i<lines.length; i++) {
			lineArray = lines[i].split(",");
		    lng = lineArray[0]*1;
		    lat = lineArray[1]*1;
		    if(!isNaN(lat+lng)){
		    	point = new GLatLng(lat,lng);
		    	points.push(point);
		    }
		}
		
		var polygon = new GPolygon(points);
		this.polygonBounds = polygon.getBounds();
		
		if (this.restrictPolygon) {
			this.form.find('#search_region').val(search_region.data);
		}
		
		this.gmap.setCenter(this.polygonBounds.getCenter());
		this.gmap.setZoom(search_region.zoom * 1);
	},
	
	doSearch : function() {
		$(document.body).css('cursor', 'wait');
		this.clearMarkers();
		this.resultsContainer.html('<img src="/images/map/loading.gif" alt="Loading..." />');
		
		var bounds = null;
		if(this.form.find('#search_region').val()) {
			bounds = this.polygonBounds;
		} else {
			bounds = this.gmap.getBounds();
		}

		var ne = bounds.getNorthEast();
		$('#top_lat').val(ne.lat());
		$('#top_lng').val(ne.lng());
		
		var sw = bounds.getSouthWest();	
		$('#btm_lat').val(sw.lat());
		$('#btm_lng').val(sw.lng());

		if (!this.form.find('#search_region').val()) {
			this.countSearch();
		}
		this.mapSearch();
	},
	
	detailSearch : function() {
		var obj = this;
		
		if (this.detailAjax) {
			this.detailAjax.abort();
			this.detailAjax = null;
		}
		
		this.detailAjax = $.ajax({
			'type': 'POST',
			'url': '/listings/search-results',
			'data': this.form.serialize(),
			'dataType': 'html',
			'success': function(data, status) {
				obj.resultsContainer.html(data);
				obj.setCounter(obj.page);
			}
		});
	},
	
	showMap : function(id, lat, lng, hide_address) {
		this.popup.showContent('<div id="popup_map_'+id+'" style="width: 600px; height: 450px"></div>', 
				hide_address ? 'Approximate Location' : 'Map This Property', 600, 450);
		var map = new GMap2(document.getElementById('popup_map_'+id));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		var point = new GLatLng(lat,lng);
		map.setCenter(point, 13);
		if (!hide_address) {
			var marker = new GMarker(point);
			map.addOverlay(marker);
			var address = $('#listing_'+id+' .address').html();
			marker.openInfoWindowHtml(address);
			GEvent.addListener(marker, 'click', function() {
				marker.openInfoWindowHtml(address);
			});
		}
	},
	
	showPhotos : function(id) {
		this.popup.showUrl('/listings/photos/id/'+id, 
				'Property Photos', 392, 470, false);
	},
	
	saveListing : function(id) {
		$('#listing_'+id+' .icon-save').css('display', 'none');
		var obj = this;
		$.ajax({
			'type': 'POST',
			'url': '/listings/save-listing',
			'data': {'property_id': id},
			'dataType': 'json',
			'success': function(data, status) {
				if(data) {
					if (data == 'auth') {
						$('#listing_'+id+' .icon-save').css('display', 'inline');
						obj.popup.showContent('<div style="padding: 10px;">'+
								'You must have an account and be logged in to save a listing.<br /><br />'+
								'<a href="/user/login">Login</a> | <a href="/user/register">Register</a>'+
								'</div>', 
								'Please Log In or Register', 400, 60);
					} else {
						obj.popup.showContent('<div style="padding: 10px;">The listing has been saved to your list.</div>', 'Listing Saved', 300, 40);
					}
				} else {
					$('#listing_'+id+' .icon-save').css('display', 'inline');
					obj.popup.showContent('<div style="padding: 10px;">An error occurred, please try again.</div>', 'Error', 300, 40);
				}
			}
		});
	},
	
	addCompare : function(id) {
		if (this.compare_properties) {
			$('#compare_data').load('/listings/compare-bar', { 'add': id }, function() {
				$('#compare_count').html('('+$('#compare_data table tr').size()+') Added');
			});
		}
	},
	
	saveSearch : function(id) {
		var center = this.gmap.getCenter();
		var params = this.form.serialize() + 
						'&lat=' + center.lat() + 
						'&lng=' + center.lng() + 
						'&zoom=' + this.gmap.getZoom();
		
		var data = {'search_params': $.base64Encode(params)};
		
		if (id) {
			data.saved_search_id = id;
		}
		
		var obj = this;
		$.ajax({
			'type': 'POST',
			'url': '/listings/save-search',
			'data': data,
			'dataType': 'json',
			'success': function(data, status) {
				if(data) {
					if (data == 'auth') {
						obj.popup.showContent('<div style="padding: 10px;">'+
								'You must have an account and be logged in to save your search.<br /><br />'+
								'<a href="/user/login">Login</a> | <a href="/user/register">Register</a>'+
								'</div>', 
								'Please Log In or Register', 400, 60);
					} else {
						obj.popup.showContent('<div style="padding: 10px;">The search has been saved to your list.</div>', 'Search Saved', 300, 40);
					}
				} else {
					obj.popup.showContent('<div style="padding: 10px;">An error occurred, please try again.</div>', 'Error', 300, 40);
				}
			}
		});
	},
	
	countSearch : function() {
		var obj = this;
		
		if (this.countAjax) {
			this.countAjax.abort();
			this.countAjax = null;
		}
		
		this.countAjax = $.ajax({
			'type': 'POST',
			'url': '/listings/search-count',
			'data': this.form.serialize(),
			'dataType': 'json',
			'success': function(data, status) {
				obj.total = data;
				obj.setupPagination();
				obj.detailSearch();
			}
		});
	},
	
	mapSearch : function() {
		var obj = this;
		
		if (this.mapAjax) {
			this.mapAjax.abort();
			this.mapAjax = null;
		}
		
		this.mapAjax = $.ajax({
			'type': 'POST',
			'url': '/listings/map-search-results',
			'data': this.form.serialize(),
			'dataType': 'json',
			'success': function(data, status) {
				obj.clearMarkers();

				if (data.length > 0) {
					if (obj.redirectIfOneResult && !obj.keywordSearchHappened) {
						obj.keywordSearchHappened = true;
						if (data.length == 1) window.location = data[0].detail_url;
					}
					$('#map_results_counter').html('(Mapped: '+data.length+')');
					obj.plotMapResults(data);
				} else {
					$('#map_results_counter').html('');
				}
				
				if (obj.form.find('#search_region').val()) {
					obj.total = data.length;
					obj.setupPagination();
					obj.detailSearch();
				}
				
				$(document.body).css('cursor', 'default');
			}
		});
	},
	
	plotMapResults : function(data) {
		var ignoreBounds = this.form.find('#ignore_bounds').val();
		var points = new Array();
		
		for (var listing in data) {
			this.addMarker(data[listing]);
			if (ignoreBounds) {
				points.push(new GLatLng(data[listing].latitude, data[listing].longitude));
			}
		}
		
		if (ignoreBounds) {
			var polygon = new GPolygon(points);
			var bounds = polygon.getBounds();
			
			this.gmap.setCenter(bounds.getCenter());
			var z = this.gmap.getBoundsZoomLevel(bounds);
			this.gmap.setZoom(z > 17 ? 17 : z);
		}
	},
	
	clearMarkers : function() {
		this.gmap.clearOverlays();
		this.markers = {};
	},
	
	addMarker : function(listing) {
		var latlng = new GLatLng(listing.latitude, listing.longitude);
		var marker = new GMarker(latlng, { icon: this.markerIcon, title: this.formatPrice(listing.price) });
		marker.listing = listing;
		this.gmap.addOverlay(marker);
		GEvent.addListener(marker, 'click', function() {
			window.open(listing.detail_url);
		});
		this.markers[listing.property_id] = marker;
	},
	
	clearMarkers : function() {
		for (var i in this.markers) {
			this.markers[i].remove();
		}
	},
	
	setupPagination : function() {
		var obj = this;
		$("#pagination_container,#pagination_container_bottom").pagination(this.total, {
			num_edge_entries: 1,
			num_display_entries: 2,
			items_per_page: $('#max_per_page').val(),
			callback: function(page, jq){
				obj.paginate(page);
			},
			link_to: '#__id__'
		});
		this.paginate(0);
	},
	
	paginate : function(page) {
		this.page = page;
		var limit = $('#max_per_page').val();
		$('#offset').val(page*limit);
		$('#limit').val(limit);
		$('#sort').val($('#sort_option').val());
		this.detailSearch();
	},
	
	setCounter : function(page) {
		var count = this.resultsContainer.find('.more_details').size();
		if (count > 0) {
			var start = 1 + (page * $('#max_per_page').val());
			var end = start + count - 1;
			$('#results_counter').html(start + ' to ' + end + ' of ' + this.total);
		} else {
			$('#results_counter').html('');
		}
	},
	
	formatPrice : function(n){
		while (this.priceRegex.test(n)) n = (n+'').replace(this.priceRegex, '$1,$2');
		return '$'+n;
	}
});
