/**
* JQuery scope extension
*/

jQuery.extend(
{
	scope: function(scope, fn)
	{
    	return function ()
    	{
        	return fn.apply(scope, arguments);
    	};
	}
});




// Global to store google maps instance
var map = null;

/**
* Crema Maps function
*/

function cremaMaps()
{
	
	// Options container
	this.defaultOptions = 
	{
          zoom: 3
        , mapTypeId: google.maps.MapTypeId.ROADMAP
        , center: new google.maps.LatLng(-25.5, 135.5)
        , mapTypeControl: false
        , updateMarkers: false
	}
	
	// Real options container
	this.options = null;
	
	this.targetElement = null;
	
	this.markers = null;
	
	// Drag timer
	// Stores the Timeout for drag actions and Ajax loading
	this.dragTimer = null;
	// Drag timer called during AJAX load? This controls if we fire the time again after AJAX load.
	this.dragDuringAjax = false;
	this.dragAllowAjax = true;
	
	/**
	* Constructor
	*
	* - Initialise map
	* - Center to Geolocation
	*/
	
	this.initialise = function( target, options )
	{
		
		/**
		* PRE LOAD OPERATIONS
		*/
		
		this.options = options;
		
		// Target Element
		this.targetElement = target;
		// Modify to Browser
	    //this.detectBrowser();
			
		/**
		* LOAD MAP
		*/
		
		// Initialise map
	    map = new google.maps.Map( document.getElementById( this.targetElement ), this.defaultOptions);
    
    
	    /**
	    * POST LOAD OPERATIONS
	    */  
	    
	    // Attempt to center on current location
    	// ASYNCHRONOUS
    	if (this.options.center.client != false)
    	{
    		this.CenterOnLoaction();
		}
		
		// Do we center on an item?
		else if ( this.options.center.item != false )
		{
			this.CenterOnItem( this.options.cafes[ this.options.center.item ] );
		}
		
		// Center by custom?
		else if ( this.options.center.custom != false )
		{
			this.CenterOnLocationCallback( this.options.center.custom );
		}
		
		// Load markers
		this.loadCafeMarkers(map, this.options.cafes);
		
		// Do we allow updating of the markers?
		if (this.options.updateMarkers == true)
		{
			// Add event listeners to boundary changes
			google.maps.event.addListener(map, 'bounds_changed', $.scope(this, this.MapMoved) );
		}
		
	}
	
	
	/**
	* Get current location and center
	*/
	
	this.CenterOnLoaction = function()
	{
		jQT.updateLocation( this.CenterOnLocationCallback );
	}
	
	this.CenterOnLocationCallback = function( coords )
	{   
		// Center on retrieved location
		var location = new google.maps.LatLng( coords.latitude, coords.longitude );
		map.setCenter( location );
		map.setZoom( this.options.center.zoom );
		
		// Add location marker
		this.updateCurrentLocationMarker( location );
	}
		
	
	/**
	* Center on ...
	* @param		object		Google LatLang position
	*/
	
	this.CenterOnItem = function( centerObject )
	{
		var location = new google.maps.LatLng( centerObject[1], centerObject[2] );
		map.setCenter( location );
		map.setZoom( this.options.center.zoom );
	}
	
	
	/**
	* Update current location marker
	*/
	
	this.updateCurrentLocationMarker = function( location )
	{
		// Does this marker already exist?
		if (this.currentLocationMarker)
		{
			// Update marker positon
			this.currentLocationMarker.setPosition( location );
		}
		else
		{
			
			// Marker image
			var image = new google.maps.MarkerImage(
				  'themes/maps/here.png'		//current location
				, new google.maps.Size(32, 32)
				, new google.maps.Point(0,0)
				, new google.maps.Point(16, 16)
			);
			
			this.currentLocationMarker = new google.maps.Marker(
			{
				  position: location
				, map: map
				, icon: image
				, clickable: false 
     		}); 
		}
	}
	
	
	/**
	* Map Moved
	*/
	
	this.MapMoved = function ()
	{
		// clear current timeout
		clearTimeout(this.dragTimer);
		
		// Instigate new timeout
		this.dragTimer = setTimeout( $.scope(this, this.AjaxGetCafes), 1000 );
	}
	
	
	/**
	* Get Cafes with AJAX
	*/
	
	this.AjaxGetCafes = function ()
	{
		// Check if Ajax is in progress		
		if (!this.dragAllowAjax)
		{
			// Set to remember that a drag happened while doing an AJAX call.
			this.dragDuringAjax = true;
			
			// Abort this call
			return;
		}
		
		// Disable further ajax calls
		this.dragAllowAjax = false;
        		
		var bounds = map.getBounds();
		var ne = bounds.getNorthEast();
		var sw = bounds.getSouthWest();
		
		// Ajax for a cafe update
		$.ajax(
		{
			type: "POST",
			url: "nearme.php",
			data: "ajax=true&action=cafeupdate&ne_x="+ne.lat()+"&ne_y="+ne.lng()+"&sw_x="+sw.lat()+"&sw_y="+sw.lng(),
			success: $.scope(this, this.AjaxGetCafes_Callback)
		});
	}
	
	
	this.AjaxGetCafes_Callback = function ( data )
	{
		// Put JSON data to page
		// Oh god this is dangerous
		data = eval( "("+data+")" );
		
		this.clearCafeMarkers(map);
		
		if (!data.error)
		{
			// Set the markers using the AJAX data
			$('#map_error').hide();
			this.loadCafeMarkers(map, data);
		}
		else
		{
			this.errorTooManyMarkers();
		}
		
		
		// Allow further AJAX calls
		this.dragAllowAjax = true;
		
		// Was there a drag during ajax?
		if (this.dragDuringAjax)
		{
			// Call the timer again
			this.MapMoved();
		}
		
		return;
	}
	
	
	/**
	* Too many markers
	* Displays message: Too many markers to display, zoom in a bit.
	*/
	
	this.errorTooManyMarkers = function ()
	{
		
		$('#map_error').text('Too many cafes to display. Please adjust your view or zoom in.');
		$('#map_error').fadeIn();
	}
	
	
	/**
	* Detected Browser
	*/
	
	this.detectBrowser = function()
	{
		var useragent = navigator.userAgent;
		if (useragent.indexOf('iPhone') != -1 || useragent.indexOf('Android') != -1 )
		{
			document.getElementById( this.targetElement ).style.width = '100%';
			document.getElementById( this.targetElement ).style.height = '100%';
		}
		else
		{
			document.getElementById( this.targetElement ).style.width = '320px';
			document.getElementById( this.targetElement ).style.height = '480px';
		}
	}
	
	
	/**
	* this.clearCafeMarkers(map);
	*/
	
	this.clearCafeMarkers = function (map, preserve)
	{
		// Do we have any preserve elements?
		if (preserve == null)
		preserve = new Array();
		
		// Clear any current markers	
		// Conditional to Preserve matching a marker
		// This stops the markers flashing
		for (var i in this.markers)
		{
			var retain = false;
			
			// Check through all preserved items
			for (var j in preserve)
			{
				if ( (this.markers[i].getPosition().lat() == preserve[j][1]) && (this.markers[i].getPosition().lng() == preserve[j][2]) )
				{
					retain = true;
				}
			}
			
			if (!retain)
			{
				this.markers[i].setMap(null);
			}
		}
		
		// Clear/Create marker array
		this.markers = new Array();
	}
	
	
	/**
	* Load cafe markers from options
	*/
		
	this.loadCafeMarkers = function(map, cafes)
	{
		// Clear/Create marker array
		this.markers = new Array();

		for (var i in cafes)
		{
			
			this.addCafeMarker(cafes[i]);
		}
	}
			

	/**
	* Add Cafe Marker
	*/
			
	this.addCafeMarker = function ( cafe )
	{
			// Marker image
			var image = new google.maps.MarkerImage(
				  'themes/maps/cafe.png'
				, new google.maps.Size(26, 14)
				, new google.maps.Point(0,0)
				, new google.maps.Point(13, 14)
			);

  			// Marker shadow
  			var shadow = new google.maps.MarkerImage(
  				  ''
				, new google.maps.Size(48, 24)
				, new google.maps.Point(0,0)
				, new google.maps.Point(24, 24)
			);
		
			// Add marker
			var marker = new google.maps.Marker(
			{
				  position: new google.maps.LatLng( cafe[1], cafe[2] )
				, map: map
//				, shadow: shadow
				, icon: image
//				, shape: shape
				, title: cafe[0]
//				, zIndex: 10
			});
					
			// Info window content
			var contentString	= '<div class="iw">'
								+ '<a href="'+cafe[3]+'" title="'+cafe[0]+'">'+cafe[0]+'</a>'
								+ '</div>';
							
			// Infowindow
			var infowindow = new google.maps.InfoWindow(
			{
				content: contentString
			});
			
			// Listener
			google.maps.event.addListener(marker, 'click', function() 
			{
				$.ajax(
				{
					  url: cafe[3]
					, async: true
					, success: function(data)
					{
						//$("#jqt").append(data);                 
						//alert(data);
						var mapCont = document.getElementById("map_load_container");
					
						if(mapCont == null){
//alert('map_load_container doesn\'t exist, and is now created');
							$('body').append('<div id="map_load_container"></div>');
						}else{
//alert('map_load_container exists');
						}
						
//alert("Getting inner HTML of map_load_container before clear\n" + document.getElementById('map_load_container').innerHTML);
						$('#map_load_container').html('');
//alert("Getting inner HTML of map_load_container after clear\n" + document.getElementById('map_load_container').innerHTML);
						$('#map_load_container').append(data);
//alert("innerHTML of map_load_container after append\n" + document.getElementById('map_load_container').innerHTML);
						
						//$('body').append(data);
						var id = $(data).find("div").parent().attr("id");
        				jQT.goTo("#" + "map_load_container", "slide");
					}
				}); 
			});
			
			this.markers.push(marker);
	}
}

/*

alert()
						$('body').append('<div id="map_load_container"></div>');
						
						$('#map_load_container').append(data);
						var id = $(data).find("div").parent().attr("id");
        				jQT.goTo("#" + id, "slide");
					}
					
					if(mapCont == null){
							$('body').append('<div id="map_load_container"></div>');
						}
						$('#map_load_container').html('');
						$('#map_load_container').append(data);
						
						//$('body').append(data);
						var id = $(data).find("div").parent().attr("id");
        				jQT.goTo("#" + "map_load_container", "slide");
*/

