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],
		onClick: 	false
	},

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

	initialize: function( el ) {
		
		if( arguments[1] ) {
			this.options = $H( arguments[1] ).combine( $H(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 );
		}

		if( this.options.onClick ) {
			var obj = this;
			GEvent.addListener( this.map, 'click', function() {
				if( !(arguments[0] instanceof GMarker) ) {
					obj.options.onClick();
				}
			} );
		}

	},
	
	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,
	didClick:	false,
	
	options: 	{
		icon:			false,
		content:		false,
		infowWindow:	false,
		onClick:		false
	},
	
	initialize: function( marker, parent, icon ) {

		if( arguments[2] ) {
			this.options = $H( arguments[2] ).combine( $H(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;
		if( this.options.onClick ) {
			GEvent.addListener( this.marker, 'click', function() {
				obj.map.setCenter( obj.marker.getPoint() );
				obj.options.onClick();
			} );
		} else {
			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() {
		this.map.setCenter( this.marker.getPoint() );
		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( $H(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();
	}
	
});

/*
	where mapData is
	{
		locations: [
			{
				id: int,
				name: string,
				latLng: [lat, lng],
				tpl: string (only if using iframe info windows)
				infoWindow: DOM object (only if using standard info windows)
			}
		],
		infoWindowURL: string (only if using iframe info windows),
		infoWindowType: string (iframe|default),
		zoomLevel: int
	}
*/

initMap = function( mapData ) {
	if( !GBrowserIsCompatible() ) {
		return false;
	}

	window.triggerClose = function() {
		GEvent.trigger( map.map, 'click' );
	}

	var coords = $('map').getCoordinates();
	
	var offsetTop = coords.top + 20;
	var offsetLeft = coords.left + 20;
	var offsetWidth = coords.width - 40;
	var offsetHeight = coords.height - 40;
	var infoWindowOpen = false;
	
	if( mapData.infoWindowWidth ) {
		offsetWidth = mapData.infoWindowWidth;
		offsetLeft = coords.left + (offsetWidth/4);
	}

	var zoomLevel = 13;
	if( mapData.zoomLevel ) {
		zoomLevel = mapData.zoomLevel;
	}
	
	var	latLng = [42.734, -84.4794];
	if( mapData.center ) {
		latLng = mapData.center;
	}
	
	var iconSize = [20,40];
	if( mapData.iconSize ) {
		iconSize = mapData.iconSize;
	}
	
	var baseIcon = false;
	if( mapData.baseIcon ) {
		baseIcon = mapData.baseIcon;
	}
	
	var iconAnchor = [0,40];
	if( mapData.iconAnchor ) {
		iconAnchor = mapData.iconAnchor;
	}
	
	var map = new TSN.GMap( 'map', {
		iconSize: iconSize,
		iconAnchor: iconAnchor,
		infoWindowOffset: [225, 20],
		zoom: zoomLevel,
		latLng: latLng,
		icon: baseIcon,
		onClick: function() {
			if( infoWindowOpen && infoWindow ) {
				infoWindowOpen = false;
				loaderWindow.setStyle( 'height', 0 );
				windowTween.set( 0 );
				infoWindow.setStyle( 'height', 0 );
			}
		}
	} );  

	if( mapData.infoWindowType == 'iframe' ) {
		var infoWindow	=  new Element( 'iframe', {
			id:	 'info-window',
			src: mapData.infoWindowURL,
			styles: {
				'position':	'absolute',
				'top': 		offsetTop,
				'left':		offsetLeft,
				'width':	offsetWidth,
				'height':	offsetHeight,
				'border': 'none',
				'overflow': 'auto'
			},
			events: {
				load: function() {
					if( mapData.autoHide ) {
						mapData.autoHide = false;
						return;
					}
					infoWindowOpen = true;
					loaderWindow.setStyle( 'height', 0 );
					windowTween.start( 0, 1 );
				}
			}
		});
		var windowTween = new Fx.Tween( infoWindow, {property:'opacity'} );
		$(document.body).adopt( infoWindow );
		windowTween.set( 0 );

		var loaderWindow = new Element( 'div', {
			'id':	'loader-window',
			'styles':	{
				'position':	'absolute',
				'background': '#fff url( /kAssets/image/spinner_new.gif ) no-repeat center center',
				'top':	coords.top+(coords.height - 100)/2,
				'left':	coords.left+(coords.width - 100)/2,
				'width':	100,
				'height':	0,
				'opacity':	.75,
				'overflow': 'auto'
			}
		});
		$(document.body).adopt( loaderWindow );
	}
	
	var markers = {};
	mapData.locations.each( function( location ) {
		markers[location.id] = map.addMarker( {
			// marker location
			latLng:		location.latLng,
			icon:		TSN.path()+'images/markers/marker_'+location.type
				+'.gif',
			onClick:	function() {
				if( infoWindow ) {
					loaderWindow.setStyle( 'height', 100 );
					infoWindow.setStyle( 'height', offsetHeight );
					$('info-window').set( 'src', mapData.infoWindowURL+'?'+
						location.tpl );
				} else {
					map.map.openInfoWindowHtml( 
						new GLatLng( location.latLng[0], location.latLng[1] ),
						location.infoWindow );
				}
			}
		}); // end addMarker
		
		if( $('list-container')) {
			$('list-container').adopt(
				new Element( 'li', {
					'class': 'list-'+location.type,
					'styles': {
						'list-style-type': 'none',
						'font-family': 'Helvetica, Arial, sans-serif',
						'padding': 0,
						'margin': '1em 0'
					}
				}).adopt( 
					/*new Element( 'img', {
						'src': TSN.path()+'images/specials/mh08-map/'+
							location.type+'.gif'
					}),*/
					new Element( 'a', {
						'text':		location.name,
						'id':		location.id,
						'href':		'#',
						'events':	{
							'click':	function(e) {
								e.stop();
								GEvent.trigger( markers[this.id].marker, 'click' );
							}
						}
					})
				)
			);
		}
		
	}); // end each
	
	return [map,markers];
};