function Mapping() {
	var me = this;
	var map;
	var allMarkers = [];
	var customMarkerIcons = [];
	var clusterer;
	var moveListener;
	var initialPub;
	var messageDiv = $('#message');
	var fetchUrl = "fetchData.php"; // "fetchDataStatic.php"

	function getExistingMarkerIndex(pub) {
		var index = -1;

		for (var i = 0; i < allMarkers.length; i++) {
			if (allMarkers[i].url == pub.url) {
				index = i;
				break;
			}
		}
		
		return index;
	}
	
	function getIconForPubRating(pubRating) {
		if (pubRating > 7) {
			return customMarkerIcons[0];
		} else if (pubRating > 4.2) {
			return customMarkerIcons[1];
		} else {
			return customMarkerIcons[2];
		}
	}

	function showLoading() {
//		$('#map').block();
	}
	
	function hideLoading() {
//		$('#map').unblock();
	}
	
	function createPub(pub, html) {
		// check we haven't added this pub to the map already
		var markerIndex = getExistingMarkerIndex(pub);

		if (markerIndex == -1) {
			addPubMarkerToMap(pub, html);
			markerIndex = allMarkers.length;
		}

		return markerIndex;
	}

	function addPubMarkerToMap(pub, html) {
		// Create the new marker
		var icon = getIconForPubRating(pub.rating);
		var point = new GPoint(pub.lon, pub.lat);
		var marker = new GMarker(point, icon);
		marker.html = "<div id='popupPubDetail'>" + html + "</div>";
		marker.url = pub.url;
	
		GEvent.addListener(marker, 'click', function(overlay, point) {
			marker.openInfoWindowHtml(marker.html);
		});

		// Add marker to the clusterer
		clusterer.addMarker(marker);
		allMarkers.push(marker);
	}
	
	function getBaseIcon() {
		var baseIcon = new GIcon();
		baseIcon.shadow = "http://www.socialanimal.com/pubs/images/shadow50.png";
		baseIcon.iconSize = new GSize(20, 34);
		baseIcon.shadowSize = new GSize(37, 34);
		baseIcon.iconAnchor = new GPoint(9, 34);
		baseIcon.infoWindowAnchor = new GPoint(9, 3);
		return baseIcon;
	}

	function createPubHtml(pub, centerPos, zoom) {
		var linkToThisPubHtml = "<a href='default.htm?lat=" + centerPos.y + "&lon=" + centerPos.x + "&z=" + zoom + "&pub=" + pub.url + "'>Link to this pub</a>";
		var html = "<a target=\"_blank\" href=\"" + pub.url + "\">" + pub.name + "</a> " + pub.rating + "/10<br>" + pub.address + "<br><br>" + linkToThisPubHtml;
		
		return html;
	}
	
	function center(point) {
		map.panTo(point);
	}
	
	function setMessage(message) {
		$(messageDiv).css({backgroundColor: 'red'});
		$(messageDiv).text(message).show();
		$(messageDiv).fadeOut(3000);
	}

	function fetchPubsForGeoArea() {
		var bounds = map.getBounds();
		var url = fetchUrl + "?maxLon=" + bounds.getNorthEast().lng() + "&maxLat=" + bounds.getNorthEast().lat() + "&minLon=" + bounds.getSouthWest().lng() + "&minLat=" + bounds.getSouthWest().lat();
		
		var centerPos = map.getCenter();
		$("#permaLink", '#footer').attr("href", "default.htm?lat=" + centerPos.lat() + "&lon=" + centerPos.lng() + "&z=" + map.getZoom());

		showLoading();
		
		$.getJSON(url, me.handleServerResponse);
	}

	this.handleServerResponse = function(responseObjects) {
		var centerPos = map.getCenter();
		var zoom = map.getZoom();
		$('div#detail', '#leftcolumn').html('');
		
		if (responseObjects.pubs.length > 0) {
			var markerIndex;
			var htmlForAllPubs = [];

			for (var i = 0; i < responseObjects.pubs.length; i++) {
				var pub = responseObjects.pubs[i];
				var html = createPubHtml(pub, centerPos, zoom);
		  		markerIndex = createPub(pub, html);

				htmlForAllPubs.push("<div class='publeft'>" + html + "</div>");
			}

			$('div#detail', '#leftcolumn').html(htmlForAllPubs.join(''));

			selectDefaultPub(me.initialPub);
		}
	
		hideLoading();
	}

	this.centerOnPub = function(index) {
		GEvent.trigger(allMarkers[index], 'click');
	}
	
	this.moveToPostcode = function() {
		var place = $('#postcode', '#header').val();
		me.geocoder.getLatLng(place, center);
	}

	this.lookForNewPlaces = function() {
		var url = "parseBITE.php?l=" + $('#place').val().replace(' ', '+');
		var request2 = GXmlHttp.create();
		request2.open('GET', url, true);
		request2.send(null);
		showLoading();
		setTimeout(fetchPubsForGeoArea, 5000);
		setTimeout(fetchPubsForGeoArea, 10000);
		setTimeout(fetchPubsForGeoArea, 15000);
		setTimeout(hideLoading, 17000);
	}
	
	function selectDefaultPub() {
		if (initialPub == "") return;

		for (var i = 0; i < allMarkers.length; i++) {
			marker = allMarkers[i];

			if (marker.url == initialPub) {
				// remove any existing movement listeners, then re-associate them afterwards
				removeMoveListener();
				center(marker.getPoint());
				marker.openInfoWindowHtml(marker.html);
				setTimeout(attachMoveListener, 1000);
				
				// Clear the initial pub so it doesn't affect future dragging
				initialPub = null;
				return;
			}
		}
	}

	this.initialise = function() {
		if (!GBrowserIsCompatible()) {
			alert('Sorry the Pub Finder requires Google Maps and your browser is not compatible');
			return;
		}

		map = new GMap2($('#map')[0]);
		this.geocoder = new GClientGeocoder(new GGeocodeCache());
		clusterer = new MarkerClusterer(map, [], {maxZoom:16});
		map.addControl(new GLargeMapControl());
		
		var baseIcon = getBaseIcon();
		customMarkerIcons[0] = new GIcon(baseIcon, "http://www.socialanimal.com/pubs/images/iconr_1.png");
		customMarkerIcons[1] = new GIcon(baseIcon, "http://www.socialanimal.com/pubs/images/iconr_2.png");
		customMarkerIcons[2] = new GIcon(baseIcon, "http://www.socialanimal.com/pubs/images/iconr_3.png");
		
		var qs = new Querystring();
	
		// Putney
//		var initialLon = qs.get("lon", -0.215735);
//		var initialLat = qs.get("lat", 51.461227);
//		var initialZoom = qs.get("z", 16);

		// London - Picadilly Circus
		var initialLon = qs.get("lon", -0.13335943222045898);
		var initialLat = qs.get("lat", 51.5112130950174);
		var initialZoom = qs.get("z", 16);
		initialPub = qs.get("pub", "");

		map.setCenter(new GLatLng(parseFloat(initialLat), parseFloat(initialLon)), parseInt(initialZoom));

		attachMoveListener();
		fetchPubsForGeoArea();
	}
	
	function attachMoveListener() {
		this.moveListener = GEvent.addListener(map, 'moveend', fetchPubsForGeoArea);
	}
	
	function removeMoveListener() {
		if (this.moveListener != undefined) {
			GEvent.removeListener(this.moveListener);
		}
		this.moveListener = null;
	}
	
	this.unblockUI = function() {
		$('.blockUI').click($.unblockUI);
	}
}

var m;

$(document).ready(function() {
	m = new Mapping();
	m.initialise();
	
	$("#postcode").qtip({
		content: "Be sure to include county or country information as we use Google to find your place.",
		position : { corner : { target: 'bottomLeft', tooltip: 'topLeft' }},
		show: {when: { event : "focus" }, delay: 10},
		hide: "blur"
	});
	
	$("#moveTo").click(function() {
		m.moveToPostcode();
		return false;
	});
	
	$("#lookForNewPlaces").click(function() {
		m.lookForNewPlaces();
		return false;
	});
	
	$("#pubMissingLink").click(function() {
		$.blockUI({message: "<b>Why isn't my favourite pub showing?</b><p>Pub Finder obtains its data by trawling the Beer In The Evening website, but it doesn't know about a pub until someone submits a search for pubs in that area.</p><p>So if there are no pubs in the area you want, enter the name or the postcode, hit search and The Pub Finder will try and find some pubs for you and automatically display them.</p><p align='center'><input type='button' onClick='m.unblockUI()' value='OK'>", css: {textAlign: 'left', padding: '3px', cursor: 'default'}});
	});
});

