/**
 *	Extende markers are created when googlemaps is loaded
 */

ArenaMap.Markers = (function($) {

	// constants
	var MAP_MARKER = 'marker',
		MAP_GROUP = 'group',
		MAP_POLY = 'polygon',
		MAP_OFFICE = 'office',
		MAP_REALESTATE = 'realestate',
		MAP_IMAGE = 'image',
		MAP_POLY_COLOR = '#2e9ed8',
		MAP_POLY_HIGHLIGHT = '#fff';

	/**
	 * Extending markers is possible after the googlemaps api has loaded
	 */
	function extendMarkers() {

		this.Marker = Class.extend(
			GOverlay,
			function(latlng, data) {
				this.type = MAP_MARKER;
				this.setLatLng(latlng);
				this.data = $.extend({}, ArenaMap.Markers.Defaults, data);
				this.$node = $(this.data.template);
				this.$content = this.$node.find(this.data.content);
				this.node = this.$node.get(0);
			},{			

			/**
			 * GOverlay interface methods that must be implemented
			 */
			initialize: function(map) {
				this.map = map;
				this.map.getPane(G_MAP_MARKER_PANE).appendChild(this.node);
				this.node.style.zIndex = this.zIndex;
				this._visible = true;
			},

			redraw: function() {
				if(!this.map) {
					return;
				}

				var point = this.map.fromLatLngToDivPixel(this.getLatLng());
				this.$node.css({
					left: (point.x - (this.node.offsetWidth  / 2) + this.data.offsetX) + 'px',
					top:  (point.y - this.node.offsetHeight + this.data.offsetY) + 'px'
				});
			},

			remove: function() {
				this.map.getPane(G_MAP_MARKER_PANE).removeChild(this.node);
				this._visible = false;
			},
			
			/**
			 * Custom methods
			 */
			set:function(property, value) {
				this.data[property] = value;
			},

			setType:function(type) {
				this.node.className = (type === MAP_MARKER ? type : (type + '-marker'));
				this.type = type;
			},

			setLabel: function(label) { this.label = label; },
			getLabel: function() { return this.label || this.data.label; },
			
			setLatLng: function(latlng) { 
				this.latlng = latlng; 
				this.zIndex = latlng? GOverlay.getZIndex(latlng.lat()) : 1;
			},

			getLatLng: function() { return this.latlng; },
			
			show: function() { this.$node.show(); this.redraw(); },
			hide: function() { this.$node.hide(); },
			visible: function(){ return this._visible; },
			
			addEvent:function(type, handler) {
				var marker = this;
				this.$node.bind(type, function(e){
					handler(marker);
					e.preventDefault();
				});
			},
			
			hover:function(over, out) {
				this.addEvent('mouseover', over);
				this.addEvent('mouseout', out);
			},

			click:function(handler) {
				this.addEvent('click', handler);
			},

			write: function(html) {
				this.$content.html(html);
				this.$content.find('.rounded').roundImages();
			//	this.redraw();
			}
		});

		/**
		 * PolygonMarker
		 */
		this.PolygonMarker = Class.extend(
			this.Marker, 
			function(latlng, data) {
				this.type = MAP_POLY;
				this.points = [];
				this.node.className = 'polygon-marker';
				this.set('offsetY', 12);
				this.hasBounds = true;
				
				var bounds = new GLatLngBounds();
				for(var i=0; i<data.coords.length; i++) {
					var coord = data.coords[i];
					var point = new GLatLng(coord.lat, coord.lng);
					this.points.push(point);
					bounds.extend(point);
				}

				this.setLatLng(new GLatLng(
					(bounds.getNorthEast().lat() + bounds.getSouthWest().lat()) /2,
					(bounds.getNorthEast().lng() + bounds.getSouthWest().lng()) /2
				));

				this.area = new GPolygon(this.points, MAP_POLY_COLOR, 4, 1, MAP_POLY_COLOR, 0);
				this.hiarea = new GPolygon(this.points, MAP_POLY_HIGHLIGHT, 1, 1, MAP_POLY_HIGHLIGHT, 0.25);

				var hiarea = this.hiarea;
				this.$node.bind('mouseover', function(){ hiarea.show(); });
				this.$node.bind('mouseout', function(){ hiarea.hide(); });
			},{

			initialize:function (map) {
				this.map = map;
				this.map.getPane(G_MAP_MARKER_PANE).appendChild(this.node);
				this.map.addOverlay(this.area);
				this.map.addOverlay(this.hiarea);
				this.node.style.zIndex = this.zIndex;
				
				//	this.area.hide();
				this.hiarea.hide();
				this._visible = true;
			},

			getBounds:function(){
				return this.area.getBounds();
			},

			getMarkers:function() { 
				return this.data.markers; 
			},
			
			remove:function () {
				this.map.getPane(G_MAP_MARKER_PANE).removeChild(this.node);
				this.map.removeOverlay(this.area);
				this.map.removeOverlay(this.hiarea);
				this._visible = false;
			}
		});

		/**
		 * Office
		 */
		this.Office = Class.extend(
			this.Marker,
			function () {
				this.type = MAP_OFFICE;
				this.node.className = 'office-marker';
			}
		);

		/**
		 * Tooltip
		 */
		this.Tooltip = Class.extend(
			this.Marker,
			function () {
				this.node.className = 'tooltip-marker';
				this.set('offsetY', -16);
			},{
			
			open:function(marker, latlng, message) {
				this.write(message || marker.getLabel());
				this.setLatLng(latlng || marker.getLatLng());
				this.show();
				this.redraw();
			}
		});

		/**
		 * Infowindow
		 */
		this.InfoWindow = Class.extend(
			this.Marker,
			function(latlng, data) {
				this.$node = $(
					'<div class="balloon">' + 
						'<span class="top"></span>' + 
						'<div class="balloon-info"><h2></h2></div><a class="balloon-x" href="#" rel="map-closeinfo">X</a>' + 
						'<span class="bottom"></span>' + 
					'</div>'
				);

				this.$content = this.$node.find('div.balloon-info');
				this.node = this.$node.get(0);
				this.set('offsetY', -22);
			},{

			getBounds:function() {
				var bounds = new GLatLngBounds(),
					point = this.map.fromLatLngToContainerPixel(this.latlng),
					left = (point.x - (this.node.offsetWidth/2)),
					right = left + this.node.offsetWidth,
					top = (point.y - this.node.offsetHeight),
					bottom = point.y;

				var nw = this.map.fromContainerPixelToLatLng(new GPoint(left, top));
				var se = this.map.fromContainerPixelToLatLng(new GPoint(right, bottom));
				
				bounds.extend(nw);
				bounds.extend(se);
				
				return bounds;
			}
		});

		/**
		 *	GridArea
		 */
		this.GridArea = Class.extend(
			GLatLngBounds,
			function(sw, ne) {
				this.markers = [];
			},{

			getMarkers:function() { return this.markers; },
			getMarker:function() { return this.marker; },

			removeMarkers:function() { 
				this.markers = []; 
			},
			
			addMarker:function(marker) {
				this.markers.push(marker);
			},

			createMarker:function() {
				var GridMarker = ArenaMap.Markers.GridMarker,
					point = this.markers[0].getLatLng();

				this.marker = new GridMarker(point, { label: 'multiple locations in this area' });
				this.marker.setMarkers(this.markers);

				return this.marker;
			}
		});

		/**
		 *	GridMarker
		 */
		this.GridMarker = Class.extend(
			this.Marker,
			
			function(latlng, data) {
				this.type = MAP_GROUP;
				this.setMarkers([]);
				this.node.className = 'group-marker';
			},{

			setMarkers:function(markers) { 
				this.markers = markers; 
				this.setLabel('<strong>' + this.markers.length + ' locations in this area</strong> Click to zoom in.');
				this.write(markers.length);
			},

			getMarkers: function() { 
				return this.markers; 
			}
		});	
	};

	return {
		initialize: function() {
			extendMarkers.apply(ArenaMap.Markers);
		},

		Defaults: {
			template: '<a href="#" class="marker"><span></span></a>',
			content: 'span',
			offsetX: 0,
			offsetY: 6
		}
	}

})(jQuery);