/** 
 * Launch openlayers JavaScript File. Used to add markers and modify controls to the map.
 * @author elam - Eric Lam - 24/05/2007 - 1:11:43 PM 
 * @version $Id: launchmap.js,v 1.9 2009-04-08 05:16:27 shansen Exp $
 */

/** @type OpenLayers.Map*/
var map = null;

var sphMercator = false;

/** @type OpenLayers.Popup*/
var popup = null;

/** @type OpenLayers.Popup*/
var popupShadow = null;

/** @type Double*/
var markerMinX = 180;
		
/** @type Double*/
var markerMinY = 90;

/** @type Double*/
var markerMaxX = -180;

/** @type Double*/
var markerMaxY = -90;

/**
 * must be called first.
 */
function createInitialMap(merc, usedLayers) {
	
	sphMercator = merc;
	
	proj_4326 = new OpenLayers.Projection("EPSG:4326");

	if (sphMercator) {
		map = new OpenLayers.Map( 
								'map',
								{
									projection: new OpenLayers.Projection("EPSG:900913"),
									displayProjection: proj_4326,
									units: "m",
									maxResolution: 156543.0339,
									maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34), 
									numZoomLevels: 20,									 
									controls: [new OpenLayers.Control.LayerSwitcher(),
									           new OpenLayers.Control.MouseDefaults(),
									           new OpenLayers.Control.PanZoom.PanZoomControl(),
									           new OpenLayers.Control.LogoControl()
											  ],
									buffer: 1
								} 
		);
	} else {
		map = new OpenLayers.Map( 
								'map',
								{		 
									controls: [new OpenLayers.Control.LayerSwitcher(),
									           new OpenLayers.Control.MouseDefaults(),
									           new OpenLayers.Control.PanZoom.PanZoomControl(),
									           new OpenLayers.Control.LogoControl()
											  ],
									buffer: 1
								}
		); 
	}
    
   
	
	// adds the terrapages street layer to the map
	createdLayers = getLayers(usedLayers);
	
	for (var x in createdLayers) {
        map.addLayer(createdLayers[x]);
    }

	// Adds the overview map controls
	var options = {
					layers: [map.baseLayer.clone()],
					mapOptions: {maxResolution: map.maxResolution},
					minRatio: 10,
					maxRatio: 10
				  };
	var overview = new OpenLayers.Control.OverviewMap2(options);
	map.addControl(overview);
	
	// sets an initial point of view for the map
	point = mkPoint(134,-26);
	
	map.setCenter(point, 3);        

}

/**
 * Creates a new point from the given lot/lan.
 * If sphMercator is set true, the point is also projected to the correct CRS.
 * 
 * @param lon Longitude
 * @param lat Latitude
 * @return the new point
 */
function mkPoint(lon, lat) {
	
	if (sphMercator) {
		point = new OpenLayers.LonLat(lon,lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
	} else {
		point = new OpenLayers.LonLat(lon,lat);
	}
	
	return point;
	
}

/**
 * Given an array of layer identifiers, it returns 
 * a set of layers.
 * 
 * A layer is created if its name is in the given array.
 * Depending on sphMercator is layers are using spherical
 * mercator or not. Some layers can only be used with 
 * spherical mercator set true.
 * 
 * @param setLayers array of layer identifiers
 * @return created layers
 */
function getLayers (setLayers) {
	
	layers = {};
	
	wmscprod = [
				"http://wmsc1.terrapages.net/getpngmap?",
				"http://wmsc2.terrapages.net/getpngmap?",
				"http://wmsc3.terrapages.net/getpngmap?",
				"http://wmsc4.terrapages.net/getpngmap?",
				"http://wmsc5.terrapages.net/getpngmap?",
				"http://wmsc6.terrapages.net/getpngmap?",
				"http://wmsc7.terrapages.net/getpngmap?"
			   ];
				
	osm = ["http://ares.syd.ardec.com.au/tilecache-8bitvs32bit/tilecache.py/"];
	
	for (y in setLayers) {
		switch (setLayers[y]) 
		{
		case "googlemap":
			layers.gmap = new OpenLayers.Layer.Google(
							"Google Streets", // the default
							{numZoomLevels: 20, 'sphericalMercator': sphMercator}
						);
			break;
			
		case "googlesat":
			layers.gsat = new OpenLayers.Layer.Google(
		            "Google Satellite",
					{type: G_SATELLITE_MAP, numZoomLevels: 20, 'sphericalMercator': sphMercator}
		    );
			break;
			
		case "googlehyb":
			layers.ghyb = new OpenLayers.Layer.Google(
		            "Google Hybrid",
					{type: G_HYBRID_MAP, numZoomLevels: 20, 'sphericalMercator': sphMercator}
		     );
			break;
		
		case "googlephy":
			layers.gphy = new OpenLayers.Layer.Google(
				"Google Physical",
				{type: G_PHYSICAL_MAP, 'sphericalMercator': sphMercator}
			);
			break;
		
		case "tp":

			if (!sphMercator) { 
				layers.tpstreet = new OpenLayers.Layer.WMS( 
											"TerraPages Street", 
											wmscprod, 
											{
												layers: 'UnprojectedStreet', 
												format: 'image/png' 
											}, 
											{
												wrapDateLine: true, 
												transitionEffect: 'resize'
											} 
										);
				
				
			} else {

				layers.tpmerc = new OpenLayers.Layer.WMS( 
											"TerraPages Mercator", 
											wmscprod, 
											{
												layers: 'StreetMercator', 
												format: 'image/png' 
											}, 
											{
												wrapDateLine: true, 
												transitionEffect: 'resize'
											} 
										);
			}
			break;
		
		case "vestreet":
			layers.ve = new OpenLayers.Layer.VirtualEarth(
		            "Virtual Earth Roads",
		            {'type': VEMapStyle.Road, 'sphericalMercator': sphMercator}
		    );
			break;
			
		case "vesat":
			layers.vesat = new OpenLayers.Layer.VirtualEarth(
		            "Virtual Earth Aerial",
		            {'type': VEMapStyle.Aerial, 'sphericalMercator': sphMercator}
		     );
			break;
			
		case "vehyb":
			layers.vehyb = new OpenLayers.Layer.VirtualEarth(
		            "Virtual Earth Hybrid",
		            {'type': VEMapStyle.Hybrid, 'sphericalMercator': sphMercator}
		     );
			break;
		
		
		case "osm32":
			
			if (sphMercator) { 
				layers.tposm32 = new OpenLayers.Layer.TMS( "OpenStreetMap 32bit", osm, 
						{layername: '32bit', format: 'image/png'}
					);
			}
			break;
		
		case "osm8":
			if (sphMercator) { 
				layers.tposm8 = new OpenLayers.Layer.TMS( "OpenStreetMap 8bit", osm, 
							{layername: '8bit', format: 'image/png'}
						);
			}
			break;

		case "yahoomap":
			layers.yahoo = new OpenLayers.Layer.Yahoo(
		            "Yahoo Street",
		            {'type': YAHOO_MAP_REG, 'sphericalMercator': sphMercator}
		     );
			break;
			
		case "yahoosat":
			layers.yahoosat = new OpenLayers.Layer.Yahoo(
		            "Yahoo Satellite",
		            {'type': YAHOO_MAP_SAT, 'sphericalMercator': sphMercator}
		    );
			break;
		
		case "yahoohyb":
			layers.yahoohyb = new OpenLayers.Layer.Yahoo(
		            "Yahoo Hybrid",
		            {'type': YAHOO_MAP_HYB, 'sphericalMercator': sphMercator}
		    );
			break;
			
		}
	
	}
	return layers;
	
}

/**
 * Adds a icon to map
 * 
 * @param {Object} lon
 * @param {Object} lat
 * @param {Object} image
 * @param {Object} desc
 */
function addMarker(cssName,lon,lat,image,descriptionHTML) {

	addPointToBounds(lon,lat);
	var lonlat = mkPoint(lon,lat);

	// sets up the icon/image to be used as the marker.
	var size = new OpenLayers.Size(20,20);
	var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
	var icon = new OpenLayers.Icon(image, size, offset);
	
	// displays the marker
	var newpoint = new OpenLayers.Marker(lonlat, icon );
	var markers = new OpenLayers.Layer.Markers( "Markers" );
	markers.displayInLayerSwitcher = false;
	map.addLayer(markers);
	markers.addMarker(newpoint);

	// creates the mouse control for the popups
	marker = new OpenLayers.Marker(lonlat,icon.clone());
	marker.events.register('mouseover', marker, function () {addPopup(cssName,lonlat,image,descriptionHTML)} );
	marker.events.register('mouseout', marker, function () {hidePopup()} );
	markers.addMarker(marker);
}

/**
 * Shows the popup
 * 
 * @param {Object} desc
 */
function addPopup(cssName,lonlat,image,descriptionHTML) {
	
	if (cssName == '') {
		cssName = 'toolTip';
	}
	
	// the shadow of the popup
	popupShadow = new OpenLayers.Popup.AutoHeight(cssName,lonlat,null,null,150,false);
    popupShadow.setContentHTML(descriptionHTML);
    popupShadow.setBackgroundColor("#000000");
    popupShadow.setOpacity(0.4);
	popupShadow.offset(14,14);
	
	// the popup with content
	popup = new OpenLayers.Popup.AutoHeight(cssName,lonlat,null,null,150,false);
    popup.setContentHTML(descriptionHTML);
    popup.setBackgroundColor("#dee7f7");
	popup.setBorder("1px solid black");
	popup.offset(8,8);

	// need to add the shadow first so it is drawn beneath
	map.addPopup(popupShadow);
    map.addPopup(popup);
}    

/**
 * hides the popup
 */
function hidePopup() {
	popupShadow.hide();
	popup.hide();
}

/**
 * Adds the pan zoom control where the "global" icon will
 * zoom to the extent of all the markers added to the map
 */
function addResetCentreControl() {

	//create the mouse controls, override scroll zooming (disabled)
	var mouseControl = new OpenLayers.Control.MouseDefaults();
	mouseControl.registerWheelEvents = function() {};

	//create the pan zoom control, override world zoom to bounds of markers
	var panZoomCon = new OpenLayers.Control.PanZoom.PanZoomControl()
	panZoomCon.buttonDown = function(evt) {
		if (!OpenLayers.Event.isLeftClick(evt)) return;
			switch (this.action) {
				case "panup":
					this.map.pan(0, -50);
					break;
				case "pandown":
					this.map.pan(0, 50);
					break;
				case "panleft":
					this.map.pan(-50, 0);
					break;
				case "panright":
					this.map.pan(50, 0);
					break;
				case "zoomin":
					this.map.zoomIn();
					break;
				case "zoomout":
					this.map.zoomOut();
					break;
				case "zoomworld":
					this.map.zoomToExtent(new OpenLayers.Bounds(markerMinX,markerMinY,markerMaxX,markerMaxY).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
					break;
			}
		OpenLayers.Event.stop(evt);
	};
	
	map.addControl(panZoomCon);
}

/**
 * Zoom the map to the closest zoom level centered on long/lat
 * 
 * @param {Object} lon
 * @param {Object} lat
 */
function zoomToPoint(lon,lat) {
	zoomTo(new OpenLayers.Bounds(lon,lat,lon,lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
}

/**
 * zooms the map to the given bounds.
 * 
 * @param {Object} bounds
 */ 
function zoomTo(bounds) {
	map.zoomToExtent(bounds);
}

/**
 * zoom to a point such that all added markers will be displayed.
 */
function zoomToMarkerBounds() {
	map.zoomToExtent(new OpenLayers.Bounds(markerMinX,markerMinY,markerMaxX,markerMaxY).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
}

/**
 * Update the global marker bounds with the new point that is added.
 * 
 * @param {Object} lon
 * @param {Object} lat
 */
function addPointToBounds(lon,lat) {
	markerMinX = Math.min(lon,markerMinX);
	markerMinY = Math.min(lat,markerMinY);
	markerMaxX = Math.max(lon,markerMaxX);
	markerMaxY = Math.max(lat,markerMaxY);
}
