function Label(opt_options, size) {
	this.setValues(opt_options);
	this.size_ = size;
	this.div_ = document.createElement('div');
	this.div_.className = 'cluster-total';
	this.div_.style.cssText = 'position: absolute; display: none;';
};
Label.prototype = new google.maps.OverlayView;

Label.prototype.onAdd = function() {
	this.getPanes().overlayLayer.appendChild(this.div_);
};

Label.prototype.onRemove = function() {
	this.div_.parentNode.removeChild(this.div_);
};

Label.prototype.draw = function() {
	var projection = this.getProjection();
	var position = projection.fromLatLngToDivPixel(this.get('position'));
	var div = this.div_;
	div.style.width = this.size_ + 'px';
	div.style.left = (position.x - (this.size_/2)) + 'px';
	div.style.top = (position.y - 5) + 'px';
	div.style.display = 'block';
	div.parentNode.style.zIndex = '104';
	this.div_.innerHTML = this.get('text').toString();
};

// INITIAL VARIABLES AND PROPERTIES
var map = {};
map.minZoom = 3;
map.maxZoom = 16;

// INITIALIZE
map.initialize = function() {
	map.view = new google.maps.Map($('#map-holder').get(0), {
		backgroundColor : '#ffffff',
		center : new google.maps.LatLng(32, 0),
		disableDefaultUI : true,
		mapTypeId : google.maps.MapTypeId.ROADMAP,
		noClear : true,
		scrollwheel : false,
		zoom : 3
	});
	map.initializeListeners();
	map.initializeControls();
};

// INITIALIZE CONTROLS
map.initializeControls = function() {
	$('#controls .zoom-in a').click(function(event) {
		event.preventDefault();
		map.zoomIn();
	});
	$('#controls .zoom-out a').click(function(event) {
		event.preventDefault();
		map.zoomOut();
	});
	$('#controls .world-view a').click(function(event) {
		event.preventDefault();
		map.view.setCenter(new google.maps.LatLng(32, 0));
		map.view.setZoom(3);
	});
	$('#controls .toggle-map a').click(function(event) {
		event.preventDefault();
		if ($('#love-counter').is(':hidden')){
			$('.map-box').show('slow');
			$(this).removeClass('active');
		} else {
			$('.map-box').hide('slow');
			$(this).addClass('active');
		}
		
	});
	$('#controls .my-location a').click(function(event) {
		event.preventDefault();
		map.setUserCenter(true);
	});
	$('#controls .toggle-filter a').click(function(event) {
		event.preventDefault();
		if ($('#filter').is(':hidden')){
			$('#filter .map-box').show();
			$('#filter').show('slow');
			$(this).addClass('active');
		} else {
			$('#filter').hide('slow');
			$(this).removeClass('active');
		}
	});
};

// INITIALIZE LISTENERS
map.initializeListeners = function() {
	google.maps.event.addListener(map.view, 'zoom_changed', function() {
		if (map.view.getZoom() < map.minZoom) {
			map.zoomIn();
		} else if (map.view.getZoom() > map.maxZoom) {
			map.zoomOut();
		} else {
			$(document).oneTime('1000ms',function(){
				map.markers.get();
			});
		}
	});
	google.maps.event.addListener(map.view, 'dragend', function() {
		map.markers.get();
	});
	google.maps.event.addListener(map.view, 'rightclick', function(event) {
		map.markers.add(event.latLng);
	});
	
	google.maps.event.addListener(map.view, 'bounds_changed', function(event) {
		map.setLastPosition();
	});
};

// MARKERS
map.markers = {
	'form': null,
	'active': null,
	'filter': true,
	'request': null,
	'objects': new Array(),
	'get' : function() {
		spinner.open();	
		var bounds = map.view.getBounds();
		var conditions = {
			'west': bounds.getSouthWest().lng(),
			'east': bounds.getNorthEast().lng(),
			'south': bounds.getSouthWest().lat(),
			'north': bounds.getNorthEast().lat(),
			'zoom': parseInt(map.view.getZoom())
		};
		if (map.markers.filter){
			$.each(formParams($('#filter form')), function(key, value){
				conditions[key] = value;
			});
		}
		if (map.markers.request){
			map.markers.request.abort();
		}
		map.markers.clear();
		map.markers.request = $.getJSON(
			urls['ROOT_URL'] + 'map/markers/',
			conditions
			, function(data, textStatus){
				if (!data){
					return;
				}
				if (!data.status){
					if (data.error){
						notification.open(data.error, gettext('Error'));
					} else {
						spinner.close();
					}
					return;
				}
				$('#total-holder strong').html(data.total);
				$.each(data.markers, function(index, jsonMarker) {
					var marker = map.markers.create(jsonMarker);
					if (marker){
						marker.setMap(map.view);
						map.markers.objects.push(marker);
					}
				});
				map.markers.filter = true;
				spinner.close();
			}
		);
	},
	'create' : function(jsonMarker) {
		if (jsonMarker.pk) {
			var image = new google.maps.MarkerImage(
				orientations[jsonMarker.orientation].marker,
				new google.maps.Size(19, 31),
				new google.maps.Point(0, 0),
				new google.maps.Point(9, 31)
			);
			var shape = {
				coord : [ 0, 0, 19, 0, 19, 31, 0, 31 ],
				type : 'poly'
			};
			var title = jsonMarker.comment;
		} else if (jsonMarker.total) {
			var cluster = null;
			$.each(clusters,function(index, element){
				var total = parseInt(jsonMarker.total); 
				if (total >= element.range[0] && (!element.range[1] || total < element.range[1])){
					cluster = element;
				}
			});
			var image = new google.maps.MarkerImage(
				urls['MEDIA_URL']+'img/additional/markers/cluster_'+cluster.name+'.png',
				new google.maps.Size(cluster.size, cluster.size),
				new google.maps.Point(0, 0),
				new google.maps.Point(cluster.size / 2, cluster.size / 2)
			);
			var shape = {
				coord : [ 0, 0, cluster.size, 0, cluster.size, cluster.size, 0, cluster.size ],
				type : 'poly'
			};
			var title = jsonMarker.total+gettext(' markers in this area, click for details.')	;
		} else {
			var image = new google.maps.MarkerImage(
				orientations[user.orientation].marker,
				new google.maps.Size(19, 31),
				new google.maps.Point(0, 0),
				new google.maps.Point(9, 31)
			);
			var shape = {
				coord : [ 0, 0, 19, 0, 19, 31, 0, 31 ],
				type : 'poly'
			};
			var title = jsonMarker.title;
		}
		var latLng = new google.maps.LatLng(jsonMarker.lat, jsonMarker.lng);
		var marker = new google.maps.Marker({
			'position' : latLng,
			'map' : null,
			'icon' : image,
			'shape' : shape,
			'title': title
		});
		if (jsonMarker.pk) {
			var clickEvent = function(event){
				map.markers.close();
				map.markers.details(marker, jsonMarker.pk);
			};
		} else if (jsonMarker.total) {
			marker.label = new Label({
				'map': map.view
			}, cluster.size);
			marker.label.bindTo('position', marker, 'position');
			marker.label.set('text', jsonMarker.total);
			marker.bounds = new google.maps.LatLngBounds(new google.maps.LatLng(jsonMarker.south,jsonMarker.west),new google.maps.LatLng(jsonMarker.north, jsonMarker.east));
			/*marker.range = new google.maps.Polygon({
				'path': [
					new google.maps.LatLng(jsonMarker.north, jsonMarker.west),
					marker.bounds.getNorthEast(),
					new google.maps.LatLng(jsonMarker.south, jsonMarker.east),
					marker.bounds.getSouthWest()
				],
				'fillColor': '#FF0000',
				'fillOpacity': 0.25,
				'strokeColor': "#FF0000",
				'strokeOpacity': 0.6,
				'strokeWeight': 2
			});
			marker.range.setMap(map.view);*/
			
			var clickEvent = function(event){
				var zoom = map.view.getZoom();
				map.view.fitBounds(marker.bounds);
				if (zoom == map.view.getZoom()){
					map.zoomIn();
				}
			};
		} else {
			var clickEvent = function(event){
				
			};
		}
		google.maps.event.addListener(marker, 'click', clickEvent);
		return marker;
	},
	'details': function(marker, pk){
		map.markers.active = marker;
		if (marker.infoWindow){
			marker.infoWindow.open(map.view, marker);
			return;
		}
		marker.infoWindow = new google.maps.InfoWindow({
			pixelOffset: new google.maps.Size(-42,85)
		});
		marker.infoWindow.open(map.view, marker);
		$.getJSON(urls['MAP_POPUP'], {'pk': pk},
			function(data, textStatus){
				if (!data.status){
					notification.open(data.error, gettext('Error'));
					return;
				}
				marker.infoWindow.setContent(data.marker);
				if (map.markers.form){
					map.markers.form.destroy();
				}
				google.maps.event.addListener(marker.infoWindow, 'domready', function() {
					$('.gmnoprint>div:last-child').addClass('last');
					$('.gmnoprint #map-overlay-details a.close-info-window').click(function(event){
						event.preventDefault();
						marker.infoWindow.close();
					});
					$('.gmnoprint form.ajax').each(function(){
						appendForm($(this));
					});
					$('.gmnoprint form.infieldlabel').each(function(){
						appendInFieldLabel($(this));
					});
				});
			}
		);
	},
	'add': function(latLng){
		if (map.markers.form){
			map.markers.form.destroy();
		}
		map.markers.form = map.markers.create({
			'lat': latLng.lat(),
			'lng': latLng.lng(),
			'title': null
		});
		map.markers.form.destroy = function(){
			$('#map-overlay-details').appendTo('#add-marker');
			map.markers.form.infoWindow.close();
			map.markers.form.setMap(null);
			map.markers.form = null;
		};
		map.markers.form.infoWindow = new google.maps.InfoWindow({
			pixelOffset: new google.maps.Size(-42, 85)
		});
		map.markers.form.setMap(map.view);
		$('#add-marker').show();
		map.markers.close();
		map.markers.form.infoWindow.setContent('<div style="height:'+$('#map-overlay-details').height()+'px; width:'+$('#map-overlay-details').width()+'px;" id="add-marker-pin"></div>');
		$('#add-marker').hide();
		google.maps.event.addListener(map.markers.form.infoWindow, 'domready', function() {
			$('.gmnoprint>div:last-child').addClass('last');
			$('#map-overlay-details').appendTo('.gmnoprint #add-marker-pin');
			$('.gmnoprint input[name=marker_lat]').val(latLng.lat().toFixed(6));
			$('.gmnoprint input[name=marker_lng]').val(latLng.lng().toFixed(6));
			$('.gmnoprint #add-marker-pin a.close-info-window').click(function(event){
				event.preventDefault();
				if (map.markers.form){
					map.markers.form.destroy();
				}
			});
		});
		map.markers.form.infoWindow.open(map.view, map.markers.form);
	},
	'clear' : function() {
		$.each(map.markers.objects,function(index, marker){
			if (marker.label){
				marker.label.setMap(null);
			}
			if (marker.range){
				marker.range.setMap(null);
			}
			marker.setMap(null);
			delete marker;
		});
		map.markers.objects = [];
	},
	'close': function(){
		if (map.markers.active){
			map.markers.active.infoWindow.close();
			map.markers.active = null;
		}
	}
};

// ZOOM IN
map.zoomIn = function() {
	map.view.setZoom(map.view.getZoom() + 1);
};

// ZOOM OUT
map.zoomOut = function() {
	map.view.setZoom(map.view.getZoom() - 1);
};

// CENTER TO USER'S LOCATION (IF FOUND)
map.setUserCenter = function(notify) {
	spinner.open();
	if (navigator.geolocation) {
		if (!navigator.geolocation.getCurrentPosition(function(position){
			notification.close();
			var location = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
			map.view.setCenter(location);
			map.view.setZoom(11);
		}, function(err){
			map.view.setZoom(3);
		})){
			if (!$.cookie('map-location')){
				$.cookie('map-location','1');
				notification.open(gettext('Look up up up up, see that nice little grey bar asking very politely to allow IJML to locate you? No? Look again! See it now? Good, now accept it!'));
			}
		}
	} else if (google.gears) {
		var geo = google.gears.factory.create('beta.geolocation');
		geo.getCurrentPosition(function(position) {
			var location = new google.maps.LatLng(position.latitude, position.longitude);
			map.view.setCenter(location);
			map.view.setZoom(11);
		});
	} else if (user.location && user.location.lat && user.location.lng){
		map.view.setCenter(new google.maps.LatLng(user.location.lat, user.location.lng));
		map.view.setZoom(user.location.zoom);
	} else {
		if (notify){
			notification.open(gettext('We could not find your location!<br />Use one of the supported browsers (Chrome, Firefox 3.5+)<br />or<br />Try typing your address in the search box.'), gettext('Are you in a jungle?'));
		}
		map.view.setZoom(3);
	}
};

// RESIZE
map.resize = function(){
	$('#map-holder').css('height', $(window).height() - $('#header').height()+5);
};

// SET LAST POSITION
map.setLastPosition = function(){
	var options = {
		path:'/'
	};
	var center = map.view.getCenter();
	$.cookie('positionLat',center.lat(),options);
	$.cookie('positionLng',center.lng(),options);
	$.cookie('positionZoom',parseInt(map.view.getZoom()),options);
};

$(window).resize(function() {
	map.resize();
});

$(window).ready(function() {
	map.resize();
	map.initialize();
	if ($.cookie('positionLat') && $.cookie('positionLng') && $.cookie('positionZoom')){
		map.view.setCenter(new google.maps.LatLng($.cookie('positionLat'),$.cookie('positionLng')));
		map.view.setZoom(parseInt($.cookie('positionZoom')));
	} else {
		map.setUserCenter();
	}
	$('#info-box .toggler').click(function(event){
		event.preventDefault();
		$('#introduction').toggle('slow');
		$('#live-feed').toggle('slow');
		$(this).toggleClass('tip-top, tip-bottom');
	});
	$('#filter button:submit').click(function(event){
		event.preventDefault();
		map.markers.get();
	});
	$('#filter a.close-info-window').click(function(event){
		event.preventDefault();
		$('#controls .toggle-filter a').click();
	});
	$('#show-more').click(function(event){
		event.preventDefault();
		$('html, body').animate({scrollTop: $('#content').offset().top}, 500);
		
	});
	$('#how-to-toggler').click(function(event){
		event.preventDefault();
		$('#how-to-text').toggle('slow');
		
	});
	$('#search-results-close').click(function(event){
		event.preventDefault();
		$('#search-results-holder').hide('slow');
		
	});
	$('#invite-holder-show').click(function(event){
		event.preventDefault();
		$(this).hide();
		$('#invite-holder').fadeIn();
		
	});
	if (user.authenticated){
		var addMarkerForm = $('#add-marker form');
		addMarkerForm.find('li.position input:checkbox').button('disable').attr('disabled','disabled').parent('li').hide();
		$.each(orientations[user.orientation].positions,function(index, value){
			addMarkerForm.find('li.position input:checkbox[value='+value+']').button('enable').removeAttr('disabled').parent('li').show();
		});
	}
	$(document).everyTime('5s','map-timer', function(i){
		$.getJSON(
			urls['ROOT_URL'] + 'map/live-feed/',
			{}
			, function(data, textStatus){
				if (!data || !data.status){
					return;
				}
				$('#live-feed ul li:first').before(data.marker).prev().hide().fadeIn('slow');
				$('#live-feed ul li:last').remove();
			}
		);
		$.getJSON(
			urls['ROOT_URL'] + 'map/love-counter/',
			{}
			, function(data, textStatus){
				if (!data || !data.status){
					return;
				}
				$('#love-counter').html(data.counter);
			}
		);
	});
});