if( !TSN ) { TSN = {} }

/*
Script: gmap.js
	Contains classes to generate SN and LLD specific Google maps, markers
	and info windows.

License:
	New BSD license.
*/

/*
Class: TSN.GMap
	Create and display a Google Map, add custom markers and info windows.

Arguments:
	element - the element to apply the Google Map to
	options - optional, see below
	
Options:
	zoom - (int) default zoom level. default 14
	latLng - (array) default map center as [latitude, longitude]. defulat is
	[42.734, -84.4794] (the State News offices)
	icon - (string) path to custom icon
	iconSize - (array) height and width of icon in pixels
	iconAnchor - (array) GPoint offset of the icon's anchor point on the map.
	usually this is [0,Height]
	infoWindowOffset - (array) offset for custom info windows given as GPoint
	coordinates (i.e. [x,y]). default is [0,0]

Events:
	none beyond GEvents thrown by map

Example:
	(begin code)
		var map = new TSN.GMap( 'map', {
			icon: TSN.path()+'style/images/marker.png',
			infoWindowOffset: [125, 10]
		} );
	(end)
*/
TSN.GMap = new Class({

	options:	{
		zoom:		14,
		latLng:		[42.734, -84.4794],
		icon:		false,
		iconSize:	[0,0],
		iconAnchor: [0,0],
		infoWindowOffset: [0,0]
	},

	center:		false,
	element:	false,
	map:		false,
	baseIcon:	false,

	initialize: function( el ) {
		
		if( arguments[1] ) {
			this.options = $H( arguments[1] ).combine( this.options );
		}
		
		this.element = $(el);
		this.map = new GMap2( this.element );
		
		this.map.addControl( new GSmallMapControl() );
		this.map.addControl( new GMapTypeControl() );
		
		this.center = new GLatLng( this.options.latLng[0],
			this.options.latLng[1] );
		
		this.map.setCenter( this.center, this.options.zoom );
		
		if( this.options.icon ) {
			this.baseIcon = new GIcon();
			this.baseIcon.image = this.options.icon;
			this.baseIcon.iconSize = new GSize( 
				this.options.iconSize[0], this.options.iconSize[1] );
			this.baseIcon.iconAnchor = new GPoint( 
				this.options.iconAnchor[0], this.options.iconAnchor[1] );
			this.baseIcon.infoWindowAnchor = new GPoint( 
				this.options.infoWindowOffset[0],
				this.options.infoWindowOffset[1] );
		} else {
			this.baseIcon = new GIcon( G_DEFAULT_ICON );
		}
	},
	
	addOverlay: function() {
		var overlay = new TSN.GMapOverlay( this, arguments[0] );
		
		return overlay;
	},
	
	/*
	Method: addMarker
		Place new marker on the map.
		
	Arguments:
		see argument list for TSN.GMapMarker
	
	Returns:
		object TSN.GMapMarker
	
	Options:
		see option list for TSN.GMapMarker		

	Example:
		(begin code)
			map.addMarker( {
				latLng:		[xx,yy],
				icon:		TSN.path()+'style/images/marker2.png',
				infoWindow:	'infoWindow',
				content:	$E( 'div' ).set( 'text', 'Loading...' ),
				url:		TSN.path()+'calendar/xinfo/someID'
			});

		(end)
	*/
	addMarker: function( options ) {
		
		if( options.latLng && !(options.latLng instanceof GLatLng) ) {
			point = new GLatLng( options.latLng[0], options.latLng[1] );
		} else if( options.point ) {
			point = options.point;
		}
		
		if( !(point instanceof GLatLng) ) {
			return false;
		}
		
		var marker = new TSN.GMapMarker( point, this, options );
		
		this.map.addOverlay( marker.marker );
		
		return marker;
	},
	
	removeMarker: function( marker ) {
		if( marker instanceof GMarker ) {
			this.map.removeOverlay( marker );
			return true;
		}

		if( marker instanceof TSN.GMapMarker ) {
			this.map.removeOverlay( marker.marker );
			return true;
		}
		
		return false;
	}

});

/*
Class: TSN.GMapMarker
	GMapMarkers are generated by TSN.GMap. See TSN.GMap.addMarker() for more
	information

	Arguments:
		options - see below
	
	Options:
		latLng - (array) required latitude and longitude to place the marker
		icon - (string) optional path to custom icon
		content - (DOM node) optional content for marker's info window
		infoWindow - (string) optional class name for custom info window.
		To use custom info windows see ExtInfoWindow utility at:
		http://gmaps-utility-library.googlecode.com/svn/trunk/extinfowindow/
		url - (string) url to remotely update info window via Ajax. Assumes
		return value is valid HTML. Requires infoWindow option.
		
	Example:
		(begin code)
			map.addMarker( {
				latLng:		[xx,yy],
				icon:		TSN.path()+'style/images/marker2.png',
				infoWindow:	'infoWindow',
				content:	$E( 'div' ).set( 'text', 'Loading...' ),
				url:		TSN.path()+'calendar/xinfo/someID'
			});

		(end)
*/

TSN.GMapMarker = new Class({

	marker:		false,
	parent:		false,
	map:		false,
	content:	false,
	url:		null,
	
	options: 	{
		icon:			false,
		content:		false,
		infowWindow:	false
	},
	
	initialize: function( marker, parent, icon ) {

		if( arguments[2] ) {
			this.options = $H( arguments[2] ).combine( this.options );
		}

		this.parent	= parent;
		this.map	= this.parent.map;

		var markerIcon = new GIcon( this.parent.baseIcon );
		if( this.options.icon ) {
			markerIcon.image = this.options.icon;
		}
		
		this.marker = new GMarker( marker, {icon:markerIcon} );
		
		var obj = this;
		GEvent.addListener( this.marker, 'click', function() {
			obj.open();
		} );
		
		if( this.options.content ) {
			this.setContent( this.options.content );
		}

	},


	/*
	Method: setContent
		Set content for marker's info window.
		
	Arguments:
		content - (DOM node) content for the info window
	
	Returns:
		object TSNGMapMarker
	

	Example:
		(begin code)
			marker.setContent(
				new Element( 'div', { 'text': 'Hello World' } )
			);
			
			map.addMarker( {
				latLng:		[xx,yy],
				icon:		TSN.path()+'style/images/marker2.png',
				infoWindow:	'infoWindow',
				content:	$E( 'div' ).set( 'text', 'Loading...' ),
				url:		TSN.path()+'calendar/xinfo/someID'
			}).setContent(
				$E( 'div', {'text': 'Hello World' } );
			);

		(end)
	*/
	setContent: function( content ) {
		this.content = content;
		
		return this;
	},

	/*
	Method: open
		Open marker's info window

	*/
	open: function() {
		var center = this.marker.getPoint();
		var point = new GLatLng( 
			center.y + 0.004,
			center.x
		);
		
		this.map.setCenter( point );

		if( this.options.infoWindow ) {
			this.marker.openExtInfoWindow(
				this.map,
				this.options.infoWindow,
				this.content.get('html'),
				{ajaxUrl:this.options.url}
			);
		} else {
			this.map.openInfoWindow( this.marker.getPoint(), this.content );
		}

	},
	
	/*
	Method: close
		Close marker's info window

	*/
	close: function() {
		this.map.closeInfoWindow();
	}

});

TSN.GMapOverlay = new Class({

	options:		{
		'width':		450,
		'height':		250,
		'id':			'gmap-overlay'
	},
	parent:			false,
	container: 		false,
	
	initialize: function( parent ) {
		if( arguments[1] ) {
			this.options = $H( arguments[1] ).combine( this.options );
		}

		var coords = map.element.getCoordinates();
		
		this.parent = parent;
		
		var top = Math.floor( ( coords.height - this.options.height ) / 2 );
		var left = Math.floor( ( coords.width - this.options.width ) / 2 );

		var styles = {
			position:	'absolute',
			width:		this.options.width,
			height:		this.options.height,
			top:		coords.top + top,
			left:		coords.left + left
		}
		
		this.container = $E( 'div', {
			'styles': styles,
			'id'	: this.options.id
		});
		
		$(document.body).grab( this.container );
		
		this.container.hide()
	},
	
	setContent: function( content ) {
		this.container.adopt( content );
		
		return this;
	},
	
	open: function() {
		this.parent.map.setCenter( this.parent.center );
		this.parent.map.panDirection( +0.7, 0 );
		this.container.show();
	},
	
	close: function() {
		this.container.hide();
	}
	
});