(function($) {

	var maps				= new Array;
	var directionsServices	= new Array;
	var directionsDisplays	= new Array;
	
	$.fn.googleMap = function(options, callback){
	
		init = function(element, isFirst){
			var el = $(element).parent().get(0);
			var map;
			if (isFirst)
			{
				buildElements(element, options, function(){
				});
			}
			map = maps[el.id];
			options = maps[el.id].Options;
			initialLocation = new google.maps.LatLng(options.defaultCenter[0], options.defaultCenter[1]);
			map.setCenter(initialLocation);
			
			loadMarkers(el, map.DataFile, function(el){
				var scriptText = "jQuery('#" + el.id + "_locations').accordion({autoHeight:false});";
				var script = document.createElement("script");
				script.type = "text/javascript";
				script.text = scriptText;
				document.body.appendChild(script);
				jQuery(map).trigger('loaded');
				var keys = pageQuery().getParameters();
				if (keys != null && keys.length > 0)
				{
					var locationType = null;
					var marker = null;
					
					if (jQuery.inArray('locationType', keys) > -1)
						locationType = pageQuery().getValue('locationType');
					if (jQuery.inArray('marker', keys) > -1)
						marker = pageQuery().getValue('marker');
					
					if (locationType != null){
						var locationEl = jQuery('#'+locationType).get(0);
						google.maps.event.trigger(locationEl, 'click');
					}
					
					if (marker != null){
						var markerEl = jQuery('#'+marker).get(0);
						google.maps.event.trigger(markerEl, 'click');
					}
				}
			});
			
			// Create a renderer for directions and bind it to the map.
			options.directionsOptions.map = map;
			var directionsDisplay = new google.maps.DirectionsRenderer(options.directionsOptions);
			directionsDisplay.setPanel(map.DirectionsPanel);
			directionsDisplays[el.id] = directionsDisplay;
			$(map.DirectionsBtn).click(function(){
				directions(el);
			});
			
			if (typeof callback === "function") return callback(map, el);
			
			/*
			if(navigator.geolocation) {
				navigator.geolocation.getCurrentPosition(function(position) {
					initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
					map.setCenter(initialLocation);
					alert(initialLocation);
				}, function() {
					alert("No location found");
				});
			}
			else
				alert("No Location Found");
			*/
		}
		
		buildElements = function(container, options, callback){
			var el = $(container).parent().get(0);
			var mapName =  el.id + '_map';
			var layout, mapContainer, locationsPanel, originationPanel, locations, directionsPanel, directionsBtn, address;
			var options = $.extend({}, $.fn.googleMap.defaults, options)
			
			layout = document.createElement("div");
			layout.id = el.id+"_layout";
			$(layout).attr("style", "height:" + options.height + ";width:" + options.width + ";");
			$(container).append(layout);
			
			mapContainer = document.createElement("div");
			mapContainer.id = mapName;
			$(mapContainer).attr("class", "pane ui-layout-center");
			$(mapContainer).attr("style", "float:left;");
			$(layout).append(mapContainer);			
			
			locationsPanel = document.createElement("div");
			locationsPanel.id = el.id + "_locationsPanel";
			$(locationsPanel).attr("class", "pane ui-layout-west");
			$(locationsPanel).attr("style", "display:none;float:left;");
			$(layout).append(locationsPanel);
			
			locations = document.createElement("div");
			locations.id = el.id + "_locations";
			$(locationsPanel).append(locations);
			
			originationPanel = document.createElement("div");
			originationPanel.id = el.id + "_originationPanel";
			$(originationPanel).attr("class", "pane ui-layout-north");
			$(originationPanel).attr("style", "float:left;");
				
			var div = document.createElement("div");
			div.id = el.id + "_addressCntr";
			$(originationPanel).append(div);
			
			var span = document.createElement("span");
			span.innerHTML = "Your Address:&#160;";
			$(div).append(span);
			
			address = document.createElement("input");
			address.id = el.id + "_address";
			$(address).attr("type", "text");
			$(address).attr("class", "address");
			$(address).keypress(function(event){
				if (event.which == "13"){
					event.preventDefault();
					directions(el);
				}
			});
			$(div).append(address);
			$(address).keyup(function(){
				maps[el.id].origin = $(address).val();
			});
			
			directionsBtn = document.createElement("div");
			directionsBtn.id = el.id + "_getDirections";
			directionsBtn.innerHTML = "Get Directions";
			$(div).append(directionsBtn);
			$(layout).append(originationPanel);
			
			directionsPanel = document.createElement("div");
			directionsPanel.id = el.id + "_directionsPanel";			
			$(directionsPanel).attr("style", "display:none;");
			$(directionsPanel).append("<div id='" + el.id + "_directionsClose'>Close</div>");
			$(container).append(directionsPanel);
			$('#'+el.id + "_directionsClose").click(function(){
				closeDirections(el);
			});
			
			var directionsService = new google.maps.DirectionsService();
			directionsServices[el.id] = directionsService;
			
			var mapOptions = {
				zoom: 10,
				mapTypeId: google.maps.MapTypeId.ROADMAP
			};
			var map = new google.maps.Map(mapContainer, options.mapOptions);
			maps[el.id] = map;
			map.Options = options;
			map.DataFile = map.Options.locationsFile;
			map.Markers = new Array;
			map.Layout = layout;
			map.LocationsPanel = locationsPanel;
			map.Locations = locations;
			map.DirectionsPanel = directionsPanel;
			map.DirectionsBtn = directionsBtn;
			map.Address = address;
			
			if (typeof callback === "function") return callback(map);
		}
		
		directions = function(el){
			var map = maps[el.id];
			var directionsService = directionsServices[el.id];
			var directionsDisplay = directionsDisplays[el.id];
			if (map.toAddress == null || map.toAddress == '')
			{
				alert("Please select a location.");
				$(map.Layout).layout().slideOpen("west");
				return;
			}
			if(map.origin == null || map.origin == '')
			{
				alert("Please enter your address.");
				$(map.Address).focus();
				return;
			}
			var dirOptions = {
				origin:map.origin,
				destination:map.toAddress,
				travelMode: google.maps.DirectionsTravelMode.DRIVING
			};
			directionsService.route(dirOptions, function(response, status){
				if (status == google.maps.DirectionsStatus.OK) { 
					clearMarkers(el, function(){
						directionsDisplay.setMap(maps[el.id]);
						directionsDisplay.setDirections(response);
						$(map.DirectionsPanel).show();
						$(map.DirectionsBtn).hide();
						$(map.Layout).layout().slideClose("west");
					});
				}
				else if (status == google.maps.DirectionsStatus.ZERO_RESULTS)
				{
					alert("No results were found. Please verify or refine your address");
					$(map.Address).focus();
				}
			});
		}
		
		closeDirections = function(el){
			var map = maps[el.id];
			var options = maps[el.id].Options;
			var directionsDisplay = directionsDisplays[el.id];
			showMarkers(el, function(el, marker){
				directionsDisplay.setMap(null);
				$(directionsDisplay.getPanel()).hide();
				$(map.DirectionsBtn).show();
				if (marker !== null)
					map.setCenter(marker.position);
				else
					map.setCenter(new google.maps.LatLng(options.defaultCenter[0], options.defaultCenter[1]))
				$("body").scrollTop(0);
			});
		}
		
		clearMarkers = function(el, callback){
			var map = maps[el.id];
			var markers = map.Markers;
			for(i in map.Markers)
			{
				if ((map.Markers[i] !== null) && (typeof map.Markers[i].setMap == 'function'))
				{
				    map.Markers[i].setMap(null);
				}
			}
			if (typeof callback === "function") return callback(el);
		}
		
		showMarkers = function(el, callback){			
			var map = maps[el.id];
			var markers = map.Markers;
			var marker;
			if (markers == null)
				init($(el).parent());
			else
			{
				for(i in markers)
				{
					if (map.Location)
						if(map.Location != markers[i].location)
							continue;
					if (typeof markers[i].setMap == 'function')
						markers[i].setMap(map);
					if (markers[i].selected === true)
						marker = markers[i];
				}
			}
			if (typeof callback === "function") return callback(el, marker);
		}
		
		filterByLocation = function(el){
			var location = $(this).get(0).id;
			var map = maps[$(this).get(0).mapId];
			var markers = map.Markers;
			maps[$(this).get(0).mapId].Location = location;
			for(i in markers)
			{
				if (location == 0)
				{
					markers[i].setMap(map);
				}
				else
				{
					if (markers[i].location != location)
					{
						if (markers[i].infowindow != null)
						{
							markers[i].infowindow.close();
						}
						markers[i].setMap(null);
					}
					else
						markers[i].setMap(map);
				}
			}
		}
		
		loadMarkers = function(el, filePath, callback){
			var thisMap = maps[el.id];
			var infowindow;
			//options = jQuery.extend(defaults(), options);

			$.ajax({type:"GET",url:filePath,dataType:"xml",
				success:function(data,textStatus) {
					var locationEl = document.createElement("h3");
					locationEl.id = "0";
					locationEl.innerHTML = "All Locations";
					locationEl.mapId = el.id;
					$(locationEl).data = thisMap;
					$(thisMap.Locations).append(locationEl);
					google.maps.event.addDomListener(locationEl, "click", filterByLocation);
					var div = document.createElement("div");
					div.className="links";
					div.style.height = "4px";
					$(thisMap.Locations).append(div);
					
					$(data).find('locations').each(function() {
						var type = $(this).attr("type");
						var _image = $(this).attr("image");
						var _shadow = $(this).attr("shadow");
						var _size = $.parseJSON($(this).attr("imageSize"));
						var _shadowSize = $.parseJSON($(this).attr("shadowSize"));
						var _anchor = $.parseJSON($(this).attr("anchor"));
						var _infoWinAnchor = $.parseJSON($(this).attr("infoWinAnchor"));
						var _location = this;
						
						var locationEl = document.createElement("h3");
						locationEl.id = $(_location).attr("ID");
						locationEl.innerHTML = $(this).attr("title");
						locationEl.mapId = el.id;
						$(locationEl).data = thisMap;
						$(thisMap.Locations).append(locationEl);
						var ul = document.createElement("ul");
						ul.className="links";

						$(this).find("marker").each(function(){
							var lat = parseFloat($(this).attr("lat"));
							var lng = parseFloat($(this).attr("lng"));
							if ($(this).attr("image")) {
								_image = $(this).attr("image");
							}
							if ($(this).attr("shadow")) {
								_shadow = $(this).attr("shadow");
							}
							if ($(this).attr("imageSize")) {
								_size = $.parseJSON($(this).attr("imageSize"));
							}
							if ($(this).attr("shadowSize")) {
								_shadowSize = $.parseJSON($(this).attr("shadowSize"));
							}
							if ($(this).attr("anchor")) {
								_anchor = $.parseJSON($(this).attr("anchor"));
							}
							if ($(this).attr("infoWinAnchor")) {
								_infoWinAnchor = $.parseJSON($(this).attr("infoWinAnchor"));
							}
							var html = $(this).find("html").text();
							
							var li = document.createElement("li");
							li.innerHTML = $(this).attr("name");
							li.id = $(_location).attr("ID") + "_" + $(this).attr("ID");
							ul.appendChild(li);
							var image = new google.maps.MarkerImage(_image, _size);
							var marker = null;
							if (_shadow != null)
							{
								shadow = new google.maps.MarkerImage(_shadow, _shadowSize);
								marker = new google.maps.Marker({position:new google.maps.LatLng(lat,lng),map:thisMap,icon:image,shadow:shadow});
							}
							else								
								marker = new google.maps.Marker({position:new google.maps.LatLng(lat,lng),map:thisMap,icon:image});
							$(li).data = marker;
							$(marker).id = li.id;
							marker.selected = false;
							marker.location = $(_location).attr("ID");
							marker.infowindow = null;
							fn = function() {
								if (infowindow){
									google.maps.event.trigger(infowindow, 'closeclick');
									infowindow.close();
								}
								infowindow = new google.maps.InfoWindow({content: html});
								thisMap.setCenter(marker.position);
								infowindow.open(thisMap, marker);
								maps[el.id].toAddress = marker.position;
								marker.selected = true;
								marker.infowindow = infowindow;
								google.maps.event.addListener(infowindow, "domready", function(){
									jQuery(".getDirections").click(function(){
										directions(el);
									});
								});
								google.maps.event.addListener(infowindow, "closeclick", function(){
									maps[el.id].toAddress = '';
									marker.selected = false;
								});
							};
							animate = function(){
								marker.setAnimation(google.maps.Animation.BOUNCE);
								setTimeout(function(){
									marker.setAnimation(null);
								}, 650);
							};
							
							stopAnimation = function(){
								marker.setAnimation(null);
							};
							
							google.maps.event.addDomListener(li, "click", fn);
							google.maps.event.addDomListener(li, "mouseover", animate);
							google.maps.event.addDomListener(li, "mouseout", stopAnimation);
							
							google.maps.event.addListener(marker, "click", fn);
							maps[el.id].Markers.push(marker);
						});
						google.maps.event.addDomListener(locationEl, "click", filterByLocation);
						$(thisMap.Locations).append(ul);
					});
					
					if (typeof callback == 'function') return callback(el);
				}
			});
		}
		
		pageQuery = function(){
			var q = location.search;
			if(q.length > 1)
			{
				this.q = q.substring(1, q.length);
			}
			else
			{
				this.q = null;
			}
			
			this.keyValuePairs = new Array();
			
			if(q)
			{
				for(var i=0; i < this.q.split("&").length; i++) {
				this.keyValuePairs[i] = this.q.split("&")[i];
				}
			}
			this.getKeyValuePairs = function() { return this.keyValuePairs; }
			this.getValue = function(s) {
				for(var j=0; j < this.keyValuePairs.length; j++)
				{
					if(this.keyValuePairs[j].split("=")[0] == s)
					{
						return unescape(this.keyValuePairs[j].split("=")[1]);
					}
				}
				return false;
			}
			this.getParameters = function() {
				var a = new Array(this.getLength());
				for(var j=0; j < this.keyValuePairs.length; j++)
				{
					a[j] = this.keyValuePairs[j].split("=")[0];
				}
				return a;
			}
			this.getLength = function() { return this.keyValuePairs.length; } 
			return this;
		}
		
		return this.each (
			function(){ init(this, true); }
		);
	};

	// default values
	$.fn.googleMap.defaults = {
		defaultCenter: [31.769186, -106.429367],
		locationsFile: "/locations.xml",
		mapOptions : { zoom: 10, mapTypeId: google.maps.MapTypeId.ROADMAP },
		directionsOptions : { supressMarkers:true },
		height: '400px',
		width: '400px'
	};	
	
})(jQuery);
