(function($){

	google.maps.Map.prototype.markers = new Array();
	google.maps.Map.prototype.getMarkers = function() {
	    return this.markers
	};
	google.maps.Map.prototype.clearMarkers = function() {
	    for(var i=0; i<this.markers.length; i++){
	        this.markers[i].setMap(null);
	    }
	    this.markers = new Array();
	};
	google.maps.Marker.prototype._setMap = google.maps.Marker.prototype.setMap;	
	google.maps.Marker.prototype.setMap = function(map) {
	    if (map) {
	        map.markers[map.markers.length] = this;
	    }
	    this._setMap(map);
	};

	var MapClass = function(el, options) {
		this.options = $.extend({
			colour: '#555555',
			width: 5,
			showPolylines: true,
			zoom: 2,
			mapTypeId: google.maps.MapTypeId.ROADMAP,
			center: new google.maps.LatLng(40, 0),
			zoomTo: true,
			callback: function($element){},
			getBalloonText: function(point) {		
				var templates = {
					photoCommentBalloonTemplate: "\
						<div class='#{className}'> \
							<span class='floatRight'>Day #{day}</span> \
							<b>#{timestamp}</b> \
	                                    <hr/> \
							<div class='clearfix'><img class='photo' src='#{img}' height='#{h}' width='#{w}' />#{comment}</div> \
							<hr/> \
							<p class='faint floatRight'>Posted: #{timesince} ago</p> \
							<p><img src='#{tour_type_icon}'> <img src='#{type_icon}'> <img src='#{weather_icon}'></p> \
						</div>",
					commentBalloonTemplate: "\
						<div class='#{className}'> \
							<span class='floatRight'>Day #{day}</span> \
							<b>#{timestamp}</b> \
							<hr/> \
							<div class='clearfix'>#{comment}</div> \
							<hr/> \
							<p class='faint floatRight'>Posted: #{timesince} ago</p> \
							<p><img src='#{tour_type_icon}'> <img src='#{type_icon}'> <img src='#{weather_icon}'></p> \
						</div>",
					balloonTemplate: "\
						<div class='#{className}'> \
							<span class='floatRight'>Day #{day}</span> \
							<b>#{timestamp}</b> \
							<hr/> \
							<p class='faint floatRight'>Posted: #{timesince} ago</p> \
							<p><img src='#{tour_type_icon}'> <img src='#{type_icon}'> <img src='#{weather_icon}'></p> \
						</div>"
				};
			
				if ((point.comment.stripTags().length == 0) && (point.img.length == 0)) {
					bText = $.template(templates.balloonTemplate, point);
					bText = $.template(bText, {
						className: 'balloon commentBalloon'
					});
				} else if (point.img.length > 0) {
					bText = $.template(templates.photoCommentBalloonTemplate, point);
		
					if (point.comment.length > 120) {
						bText = $.template(bText, {
							className: 'balloon photoCommentBalloon'
						});
					} else {
						bText = $.template(bText, {
							className: 'balloon photoSimpleCommentBalloon'
						});
					};
				} else {
					bText = $.template(templates.commentBalloonTemplate, point);
					bText = $.template(bText, {
						className: 'balloon commentBalloon'
					});
				};
		
				return bText;
			}	
		}, options);
		
		this.addMarker = function(point) {			
			var gmap = this.gmap;

			var marker = new google.maps.Marker({
				position: new google.maps.LatLng(point.lat, point.lon),
				map: gmap
			});
	  			/*content: $.getBalloonText(point, options),
				maxWidth: 10000*/
			var infowindow = new google.maps.InfoWindow({
				content: this.options.getBalloonText(point),
				maxWidth: 10000
			});
                  
			var callback = this.options.callback;
                  
			var $eID = $('#wp' + point.id).click(function (e) {	
				if ($.lastInfoWindow) {
					$.lastInfoWindow.close(); 
				};
				$.lastInfoWindow = infowindow;
				infowindow.open(gmap, marker);
				callback($eID, point);	
			});
						
			google.maps.event.addListener(marker, 'click', function () {
				$eID.click();
			});		
		};
		
		this.addMarkers = function(points, options) {
			this.options = $.extend(this.options, options); 
		
			var gmap = this;
			
			var bounds = new google.maps.LatLngBounds();
			var polyLine = [];
			
			$.each(points, function() {
				gmap.addMarker(this);
				
				var latlng = new google.maps.LatLng(this.lat, this.lon);
				
				polyLine.push(latlng);
				bounds.extend(latlng);
			});
			
			if (this.options.showPolylines && this.options.width) {
				new google.maps.Polyline({
					path: polyLine,
					strokeColor: this.options.colour,
					strokeOpacity: 1.0,
					strokeWeight: this.options.width
				}).setMap(this.gmap);						
			};
			
			if (this.options.zoomTo) {
			 	this.gmap.fitBounds(bounds);	
			};
		};
		
		this.removeMarkers = function(points) {
			if ($.lastInfoWindow) {
				$.lastInfoWindow.close(); 
			};
			this.gmap.clearMarkers();
		};

		// naming is confusing here
		this.gmap = new google.maps.Map(el, this.options);
		$(el).data('gmap', this);
	}
	
	$.fn.trackmytour = function(options) {
		return this.each(function() {
			(new MapClass(this, options));
		});
	}
})(jQuery);


$.extend(String.prototype, {
	stripTags: function () {
		return this.replace(/<\/?[^>]+>/gi, '');
	}
});

jQuery.extend({
	template: function (s, o) {
		return s.replace(/#{([^{}]*)}/g, function (a, b) {
			var r = o[b];
			return typeof r === 'string' || typeof r === 'number' ? r : a;
		});
	}
});