// JavaScript Document


/* Map.js 


TO-DOs
- Add 'none' option for controls - DONE
- Add Controls for Bing - DONE
- Add basic map stuff for multimap - DONE

COMMENTS - DONE

- Add Markers for all maps - DONE
- custom Icons for markers
- Add Marker Text / html

COMMENTS!

- Add html table maker import
- Add xml marker import
- Add kml marker import
- Add other proprietry marker import
- JSON Marker import

COMMENTS!

- rerwite for jQuery

COMMENTS!

*/

var Map = new Class({
				  
	map : '', // holds map object
	element : '', // holds map container id
	mapPoint : '', // the LatLng object holding current map position (before it's moved by user)

	options : {
		provider : 'google', // map provider, can be 'google', 'microsoft' or 'multimap'
		latitude : 51.508609, // latitude of starting position
		longtitude : -0.126436, // longtitude of starting position
		zoom: 15, // zoom level of starting position
		address : false, // string representation of address to search for - overrides latitude and longtitude
		marker : false, // if true, will place a default marker at the point given by latitude/longtitude or search options
		controls : 'reduced', // amount of controls to show - can be "none", "basic", "reduced", or "full"
		overlay : false, // whether to show small map overlay
		scale : false, // whether to show scale bar (google or mirosoft only)
		onLoad : $empty, // map load event
	},
	
	Implements: [Options, Events],
	
/*
	CONSTRUCTOR
	
	new Map( element:string, options:object):object
	
	arguments
		element[string] - the id of the container element, must be an id no other selectors will work
		options[object] - the options object, see above
	returns
		a new instance of the map object
	called by
		User
	calls
		nothing - adds events to call functions when page is finished loading
*/
	
	initialize: function(element, options){
		this.setOptions(options);
		this.element = element;
		if( this.options.provider == 'google' ){
			window.addEvent('load', this.addGoogleMap.bind(this) );
			google.load("maps", "2", {"other_params":"sensor=false"});
		}else if( this.options.provider == "microsoft" ){
			this.map = null;
			window.addEvent('load', this.addBingMap.bind(this) );
		}else if( this.options.provider == "multimap" ){
			window.addEvent("load", this.addMultiMap.bind(this) );
		}
	},

/*
	getLatLong(lat:Number, long:Number):Object
	
	Returns correct latitude/longtitude representational object depending on provider
	
	arguments
		lat - the latitude of required point
		long - the longtitude of required point
	returns
		either google.maps.LatLng object, VELatLong object or MMLatLon object depending on provider
	called by
		addGoogleMap, addBingMap, addMultiMap
	calls
		none
*/

	getLatLong: function(lat, long){
		var LatLng;
		if( this.options.provider == "google"){
			LatLng = new google.maps.LatLng(lat, long);
		}else if( this.options.provider == "microsoft"){
			LatLng = new VELatLong(lat, long);
		}else if( this.options.provider == "multimap"){
			LatLng = new MMLatLon( lat, long );
		}
		this.mapPoint = LatLng;
		return LatLng;
	},
	
/*
	addGoogleMap():void
	
	adds a google map to the page
	
	arguments
		none
	returns
		nothing
	called by
		Event:Window.load
	calls
		addControlGoogle
*/
	
	addGoogleMap: function(){
		this.map = new google.maps.Map2( $(this.element) );
		if( this.options.address ){
			var geocoder = new GClientGeocoder();
			geocoder.getLatLng( this.options.address,
    			function(point) { 
					if (point){
						this.map.setCenter(point, this.options.zoom);
						if( this.options.marker ) this.map.addOverlay(new GMarker( point ) ); 
					}
 		   }.bind(this) );
		}else{
        	this.map.setCenter( this.getLatLong(this.options.latitude, this.options.longtitude), this.options.zoom);
			if( this.options.marker ) this.map.addOverlay( new GMarker( this.getLatLong(this.options.latitude, this.options.longtitude) ) );
		}
		this.addControlGoogle();
		this.fireEvent('load');
	},
	
/*
	addBingMap():void
	
	adds a bing (mircosoft) map to the page
	
	arguments
		none
	returns
		nothing
	called by
		Event:Window.load
	calls
		addControlBing
*/
	
	addBingMap: function(){
		 this.addControlBing();
		 if( this.options.address){
			 	this.map.Find(null, this.options.address);
		 }
		 // the code below doesn't work! need to find way to get current position
		 /*if(this.options.marker){
			 var shape = new VEShape(VEShapeType.Pushpin, this.map.GetCenter() );
			 this.map.AddShape(shape);
		 }*/
		 this.fireEvent('load');
	},
	
/*
	addMultiMap():void
	
	adds a multimap to the page
	
	arguments
		none
	returns
		nothing
	called by
		Event:Window.load
	calls
		addControlMultiMap
*/	
	
	addMultiMap: function(){
		this.map = new MMFactory.createViewer( $( this.element ) );
  		this.map.goToPosition( new MMLocation( this.getLatLong(this.options.latitude, this.options.longtitude) , this.options.zoom ) );
		this.addControlMultiMap();
		this.fireEvent('load');
	},
	
/*
	addControlGoogle():void
	
	adds controls onto the map, depending on options
	
	arguments
		none
	returns
		nothing
	called by
		addGoogleMap()
	calls
		*
*/
	addControlGoogle: function(){
		if( this.options.controls != 'none'){
			switch(this.options.controls){
				case "basic" :
					this.map.addControl( new GSmallZoomControl3D() );
					break;
				case "reduced" :
					this.map.addControl( new GSmallMapControl() );
					this.map.addControl( new GMapTypeControl() );
					break;
				case "full" :
					this.map.addControl( new GLargeMapControl3D() );
					this.map.addControl( new GMapTypeControl() );
					break;
			}
			if( this.options.overlay ) this.map.addControl( new GOverviewMapControl() );
			if( this.options.scale ) this.map.addControl( new GScaleControl() );
		}
	},

/*
	addControlBing():void
	
	adds controls onto the map, depending on options
	
	arguments
		none
	returns
		nothing
	called by
		addBingMap()
	calls
		*
*/	
	addControlBing: function(){
		if( this.options.controls != 'none'){
			switch(this.options.controls){
				case "basic" :
					this.map = new VEMap(this.element);
					this.map.SetDashboardSize(VEDashboardSize.Tiny);
					this.map.LoadMap(this.getLatLong(this.options.latitude, this.options.longtitude), this.options.zoom ,'r' ,false);
					break;
				case "reduced" :
					this.map = new VEMap(this.element);
					this.map.SetDashboardSize(VEDashboardSize.Small);
					this.map.LoadMap(this.getLatLong(this.options.latitude, this.options.longtitude), this.options.zoom ,'r' ,false);
					break;
				case "full" :
					this.map = new VEMap(this.element);
					this.map.SetDashboardSize(VEDashboardSize.Normal);
					this.map.LoadMap(this.getLatLong(this.options.latitude, this.options.longtitude), this.options.zoom ,'r' ,false);
					break;
			}
			if( this.options.overlay ){ 
				this.map.ShowMiniMap($(this.element).getSize().x - 150, 0);
			}
			if( this.options.scale ) this.map.ShowScalebar();
		}else{
			this.map = new VEMap(this.element);
			this.map.LoadMap(this.getLatLong(this.options.latitude, this.options.lontitude), this.options.zoom ,'r' ,false);
			this.map.HideDashboard();
		}
	},
	
/*
	addControlMulitMap():void
	
	adds controls onto the map, depending on options
	
	arguments
		none
	returns
		nothing
	called by
		addMultiMap()
	calls
		*
*/	
	addControlMultiMap: function(){
		if( this.options.controls != 'none'){
			switch(this.options.controls){
				case "basic" :
					this.map.addWidget( new MMSmallZoomWidget() );
					break;
				case "reduced" :
					this.map.addWidget( new MMSmallPanZoomWidget() );
					this.map.addWidget( new  MMMapTypeWidget() );
					break;
				case "full" :
					this.map.addWidget( new MMPanZoomWidget( new MMBox( 10, 10, undefined, undefined ) ) );
					this.map.addWidget( new  MMMapTypeWidget() );
					break;
			}
			if( this.options.overlay ) this.map.addWidget( new MMOverviewWidget() );
		}
	},
	
	addMarker: function(lat, long, options){
		var options = options || {}; 
		switch(this.options.provider){
			case "google":
				var opt = { clickable : false };
				options = $merge( opt, options);
				this.map.addOverlay(new GMarker( this.getLatLong(lat, long), options ) ); 
				break;
			case "multimap":
				var opt = {};
				options = $merge( opt, options);
				this.map.createMarker( this.getLatLong(lat, long), options );
				break;
			case "microsoft":
				var shape = new VEShape(VEShapeType.Pushpin, this.getLatLong(lat, long) );
				this.map.AddShape(shape);
				break;

		}
	}

			
				
	
				  
});


