function MarkerCollection() {
	this.markers = [];

	MarkerCollection.prototype.add = function(marker) {
		this.markers[this.markers.length] = marker;
	};

	MarkerCollection.prototype.get = function(index) {
		return this.markers[index];
	};

	MarkerCollection.prototype.size = function() {
		return this.markers.length;
	};

	// find an overlapping Marker
	MarkerCollection.prototype.overlappingMarker = function(x, y) {

		for ( var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			var pointX = marker.x;
			var pointY = marker.y;

			var diffX = Math.abs(x - pointX);
			var diffY = Math.abs(y - pointY);

			if (diffX < 10 && diffY < 10) {
				return marker;
			}
		}

		return null;
	};

	MarkerCollection.prototype.list = function() {
		return this.markers;
	};
}

function Marker(point, x, y) {
	this.locations = [];
	this.point = point;
	this.x = x;
	this.y = y;

	this.setupInfoWindow = function() {
	};

	Marker.prototype.addLocation = function(location) {
		this.locations[this.locations.length] = location;
	};

	Marker.prototype.isCombined = function() {
		return this.locations.length > 1;
	};

	Marker.prototype.location = function() {
		return this.locations[0];
	};

	Marker.prototype.locations = function() {
		return this.locations;
	};

	Marker.prototype.getMarker = function() {
		var icon = new GIcon(G_DEFAULT_ICON);
		icon.iconSize = new GSize(32, 32);

		if (this.isCombined()) {
			icon.image = "http://www.fuelcelltoday.com/ktn-map/images/multiple.png";
		} else {
			icon.image = "http://www.fuelcelltoday.com/ktn-map/images/1.png";
		}

		var marker = new GMarker(this.point, icon);
		marker.location = this;
		return marker;
	};

	Marker.prototype.showInfo = function(map, latlng) {
		var point = map.fromLatLngToContainerPixel(latlng);
		var position = jQuery("#organisations-map").offset();
		$("#map-info").empty();

		var MAX_LOCATIONS = 5;

		for ( var i = 0; i < (this.locations.length > MAX_LOCATIONS ? MAX_LOCATIONS
				: this.locations.length); i++) {
			var location = this.locations[i];
			$("#map-info").append("<h3>" + location.data.name + "</h3>");
			$("#map-info").append("<p>" + location.data.location + "</p>");

			if (this.isCombined()) {
				$("#map-info").append("<a target='_blank' href='" + location.data.href + "'>View Organisation</a>");
			}
		}

		if (this.locations.length > MAX_LOCATIONS) {
			$("#map-info").append("<p class='more'>+ " + (this.locations.length - MAX_LOCATIONS) + " more</p>");
		}

		var height = $("#map-info").height();

		$("#map-info").css( {
			"left" : point.x + position.left + 20,
			"top" : point.y + position.top - (height / 2)
		});
		$("#map-info").show();
	};

	Marker.prototype.hideInfo = function(map, latlng) {
		$("#map-info").hide();
	};

	Marker.prototype.click = function() {
		if (this.isCombined()) {

			$("#map-info").hide();
			$("#map-info-sticky div").empty().append($("#map-info").html());
			$("#map-info-sticky").css( {
				"left" : $("#map-info").css("left"),
				"top" : $("#map-info").css("top")
			});
			$("#map-info-sticky").show();
		} else {
			window.location.href = this.location().data.href;
		}
	};
}

function Location(data) {
	this.data = data;
	this.point = data.point;
	Location.prototype.showInfo = function(map, latlng) {
		var point = map.fromLatLngToContainerPixel(latlng);
		var position = jQuery("#map").offset();
		$("#map-info h3").text(this.data.name);
		$("#map-info p").text(this.data.location);
		$("#map-info").css( {
			"left" : point.x + position.left + 10,
			"top" : point.y + position.top + 10
		});
		$("#map-info").show();
	};
}

function PropertyMap(element) {
	this.locations = [];
	this.markers = [];
	this.zoom = null;
	this.markerHeight = 36;
	this.markerWidth = 23;
	this.markerImagePrefix = null;
	this.map = null;
	this.element = element;

	PropertyMap.prototype.createMap = function(locations) {
		var self = this;
		var map = new GMap2(this.element);
		this.map = map;
		this.locations = locations;

		map.addControl(new GSmallMapControl());
		map.addControl(new GMapTypeControl());
		map.setMapType(G_NORMAL_MAP);

		GEvent.addListener(map, "zoomend", function(oldZoom, newZoom) {
			self.refresh(false);
		});

		self.refresh(true);
	};

	/**
	 * Refresh map
	 */
	PropertyMap.prototype.refresh = function(redraw) {
		// clear all overlays
		this.map.clearOverlays();

		var self = this;

		if (redraw == true) {
			var bounds = new GLatLngBounds();
			for ( var i = 0; i < this.locations.length; i++) {
				if (this.locations[i].point != null) {
					bounds.extend(this.locations[i].point);
				}
			}

			var map = this.map;
			var center = bounds.getCenter();
			var mapSize = map.getSize();
			var size = new GSize(mapSize.width - this.markerWidth,
					mapSize.height - this.markerHeight);

			if (this.zoom == null) {
				this.zoom = G_NORMAL_MAP.getBoundsZoomLevel(bounds, size);
			}

			// move the center down
			map.setCenter(center, this.zoom);

			var pixelCentre = map.fromLatLngToDivPixel(center);
			pixelCentre = new GPoint(pixelCentre.x, pixelCentre.y - this.markerHeight);
			center = map.fromDivPixelToLatLng(pixelCentre);

			map.panTo(center);
		}

		var groupedMarkers = new MarkerCollection();

		for ( var j = 0; j < this.locations.length; j++) {
			var location = this.locations[j];

			if (location != null && location.point != null) {
				var point = this.map.fromLatLngToContainerPixel(location.point);
				var position = jQuery("#organisations-map").offset();

				var x = point.x + position.left;
				var y = point.y + position.top;

				var marker = groupedMarkers.overlappingMarker(x, y);

				if (marker == null) {
					marker = new Marker(location.point, x, y);
					groupedMarkers.add(marker);
				}

				marker.addLocation(location);
			}
		}

		for ( var k = 0; k < groupedMarkers.size(); k++) {
			var locationMarker = groupedMarkers.get(k);
			var marker = locationMarker.getMarker();

			GEvent.addListener(marker, "mouseover", function(latlng) {
				this.location.showInfo(self.map, latlng);
			});

			GEvent.addListener(marker, "mouseout", function(latlng) {
				this.location.hideInfo(self.map, latlng);
			});

			GEvent.addListener(marker, "click", function(latlng) {
				jQuery("#map-info").hide();
				this.location.click();
			});

			this.markers[this.markers.length] = marker;
			this.map.addOverlay(marker);
		}
	};
}

// render the map
$(document).ready( function() {
	var institutions = [];
	$("div.organisation ul li").each( function() {
		var $this = $(this);
		var latLong = $this.find("span.location").text();
		if (latLong != null && latLong != "") {
			var address = $this.find("span.address").text();
			var postcode = $this.find("span.postcode").text();
			var country = $this.find("span.country").text();

			var institution = {};
			var location = address;
			if (postcode != null && postcode != "") {
				location += ", " + postcode;
			}
			location += ", " + country;
			var point = latLong.split(",");
			institution.point = new GLatLng(point[0], point[1]);
			institution.location = location;
			institution.name = $(this).find("a.title span.name").text();
			institution.href = $(this).find("a.title").attr("href");
			institutions[institutions.length] = new Location(institution);
		}
	});

	$("#map-info-sticky img").click( function() {
		$("#map-info-sticky").hide();
	});

	var map = new PropertyMap($("#organisations-map").get(0));
	map.createMap(institutions);
	map.refresh();
});
