(function($) {
	var options = {
		mapCenter: [55.3994, 10.3818],
		zoomLevel: 15,
		aboutTabText: 'About',
		contactTabText: 'Contact',
		jsonUrl: '/maps/maps/index/1.json'
	}

	$.fn.map = function(settings) {
		options = $.extend({}, options, settings); // How do I make the options var available in private functions? init, updateVisibility etc
		return this.each(function() {
			var $this = this;
			init($this);
		});
	}

	var locations = [];
	var map;

	function init(el) {
		$(document.body).unload(function() {
			if (GBrowserIsCompatible()) {
				GUnload();
			}
		});
		map = new GMap2(el);
		map.addControl(new GSmallMapControl());
		map.addControl(new GMapTypeControl());
		map.setCenter(new GLatLng(options.mapCenter[0], options.mapCenter[1]), options.zoomLevel);
		map.enableGoogleBar();
		map.GDirections = new GDirections(map)
		addMarkers();

		$('#locationsBox input[type=checkbox]').click(function() {
			var locationTypeId = $(this).metadata().location_type_id;
			if (this.checked) {
				show(locationTypeId);
			} else {
				hide(locationTypeId);
			}
		});
	}

	function updateVisibility() {
		$('#locationsBox input[type=checkbox]').each(function() {
			var locationTypeId = $(this).metadata().location_type_id;
			if (this.checked) {
				show(locationTypeId);
			} else {
				hide(locationTypeId);
			}
		});
	}

	function addMarkers() {
		var req = $.ajax({
			url: options.jsonUrl,
			type: 'get',
			cache: false,
			dataType: 'json',
			success: function(data) {
				$.each(data, function(i, item) {
					var locationType = item.LocationType;
					$.each(item.Location, function(j, location) {
						var location = location.Location;
						var icon = null;
						if (locationType.icon) {
							var iconWidth = 32;
							var iconHeight = 32;
							icon = new GIcon(G_DEFAULT_ICON);
							icon.iconSize = new GSize(iconWidth, iconHeight);
							icon.shadowSize = new GSize(59, 32);
							icon.infoWindowAnchor = new GPoint(iconWidth / 2, 0);
							icon.imageMap = [0, 0, iconWidth - 1, 0, iconWidth - 1, iconHeight -1, 0, iconHeight -1];
							icon.image = locationType.icon;
							icon.shadow = null;
						}

						var marker = new GMarker(new GLatLng(location.latitude, location.longitude), {
							icon: icon
						});

						$('#location_' + location.id).click(function(){
							var toAddress = location.street + ' ' + location.zip + ' ' + location.city + ' Denmark';
							var title = location.name;
							GEvent.trigger(marker, 'click');
							return false;
						});

						$('#location_directions_' + location.id).click(function(){
							var toAddress = location.street + ' ' + location.zip + ' ' + location.city + ' Denmark';
							var title = location.name;
							map.getInfoWindow().hide();
							drivingDirections(title, toAddress);
							return false;
						});

						GEvent.addListener(marker, 'click', function(){
							marker.openInfoWindowTabsHtml([
								new GInfoWindowTab(options.aboutTabText, location.about_tab),
								new GInfoWindowTab(options.contactTabText, location.address_tab)
							]);
						});

						map.addOverlay(marker);
						marker.data = item; // save location data as a property in marker
						locations.push(marker);


					});
				});
				updateVisibility();
				req = null;
			}
		});
	}

	show = function(id) {
		$('#location_type_' + id).show();
		$.each(locations, function(i, location){
			if (location.data.LocationType.id == id) {
				location.show();
			}
		});
	};

	hide = function(id) {
		map.getInfoWindow().hide();
		$('#location_type_' + id).hide();
		$.each(locations, function(i, location){
			if (location.data.LocationType.id == id) {
				location.hide();
			}
		});
	}

	function buildTop(name, route) {
		var string = '<h1>' + name + '</h1>';
		string += '<div class="address">' + route.getEndGeocode().address + '</div>';
		string += '<div class="distance">' +route.getDistance().html + ' (' + route.getDuration().html + ')</div>';
		return string;
	}

	function buildBottom(route) {
		var string = '';
		return string;
	}

	function buildStep(step) {
		var description = step.getDescriptionHtml();
		var distance = step.getDistance().html;
		var latLng = step.getLatLng();
		var string = '<li>' + description + ' (' + distance + ')</li>';
		return string;
	}

	function buildPanel(name) {
		var html = '';

		for (var i = 0; i < map.GDirections.getNumRoutes(); i++) {
			var route = map.GDirections.getRoute(i);
			var geocode = route.getStartGeocode();
			var point = route.getStep(0).getLatLng();

			html += buildTop(name, route);

			html += '<ol class="steps">';
			for (var j = 0; j < route.getNumSteps(); j++) {
				var step = route.getStep(j);
				html += buildStep(step);
			}
			html += '</ol>';
			html += buildBottom(route);
		}

		$('#directionsContainer').html(html);
		$('#directionsPanelWrapper').show();
		$('#locationsBoxWrapper').hide();

		$('#back').click(function(){
			backToList();
			return false;
		});
	}

	function backToList() {
		map.GDirections.clear();
		$('#directionsPanelWrapper').hide();
		$('#locationsBoxWrapper').show();
	}

	function drivingDirections(name, toAddress) {
		GEvent.addListener(map.GDirections, 'error', function() {
			alert('Unable to get directions for: ' + toAddress + '. Failed with error: ' + map.GDirections.getStatus().code);
		});
		map.GDirections.clear();
		GEvent.addListener(map.GDirections, 'load', function() {
			buildPanel(name);
		});
		map.GDirections.load('from: Hans Tausensgade 19, 5000 Odense C, Denmark to: ' + toAddress, {
			getSteps: true
		});
	}

}(jQuery));