/*
* Coverage map functions
*/

var currentCoverageAreaPolygon;

function drawCoverageAreaPolygon(aShape) {

	currentCoverageAreaPolygon = new GPolygon(aShape, "#00FF00", 2, 1, "#00FF00", 0.15);
	map.addOverlay(currentCoverageAreaPolygon);
}

function removeCoverageAreaPolygon() {
	map.removeOverlay(currentCoverageAreaPolygon);
}


/**
* Zoom to polygon
*
* @param array of vertices
*
*/
function zoomToPolygon(aShape, isGPolygon, mapObject) {

	var isGPolygon = (isGPolygon == undefined) ? false : isGPolygon;

	var strokeColor = "#00FF00";
	var strokeWeight = 3;
	var strokeOpacity = .5;
	var fillColor = "#00FF00";
	var fillOpacity = .1;

	if (isGPolygon) {
		var polygon = aShape;
	} else {
		var polygon = new GPolygon(aShape, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity);
	}

	var bounds = polygon.getBounds();
	var centerPoint = bounds.getCenter();

	var zoomLevel = mapObject.getBoundsZoomLevel(bounds);
	mapObject.setCenter(centerPoint, zoomLevel);



}

function twoPointsToBoundsPolygon(aPoints) {

	var points = new GPolygon(aPoints);
	var bounds = points.getBounds();

	var sw = bounds.getSouthWest();
	var ne = bounds.getNorthEast();
	var nw = new GLatLng(ne.lat(), sw.lng());
	var se = new GLatLng(sw.lat(), ne.lng());

	var polygon = new Array(nw, ne, se, sw, nw);
	return polygon;

}

/**
 * converts a pixel point to a google GPoint using the event variable
 *
 */
function getGPointFromPixel(e) {

	// the event variable as different values depending on the browser
	if (e.pageX || e.pageY) {
		posX = e.pageX;
		posY = e.pageY;
	} else if (e.clientX || e.clientY){
		posX = e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
		posY = e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
	}

	
	var mapDiv = map.getContainer();
	var leftPos = mapDiv.offsetLeft;    	    // initialize var to store calculations
	var topPos = mapDiv.offsetTop;         		// initialize var to store calculations
	var parElement = mapDiv.offsetParent;   	// identify first offset parent element
	while (parElement != null ) {        		// move up through element hierarchy
		leftPos += parElement.offsetLeft;     	// appending left offset of each parent
		topPos += parElement.offsetTop;
		parElement = parElement.offsetParent; 	// until no more offset parents exist
	}

	return new GPoint(posX - leftPos, posY - topPos);

}


var currentMultiPolygons = new Array();

/**
 * Draws a polygon to the map and stores all the polygons to an array, so that it can be removed and zoomed to
 * If persistant is set to true, then it just draws the polygons to the map and doesn't store it
 * @param array the polygon
 * @param boolean if the polygon should be filled
 * @param string the colour of the border
 * @param string the colour of the fill
 * @param boolean if the polygon is persistant
 *
 */
function drawMultiPolygon(polygon, fill, borderColour, fillColour, bPersistant, bIsGPolygon) {

	var fill = (fill == null) ? true : fill;
	var borderColour = (borderColour == null) ? "#ff0000" : borderColour;
	var fillColour = (fillColour == null) ? "#ff0000" : fillColour;
	var bPersistant = (bPersistant == null) ? false : bPersistant;
	var bIsGPolygon = (bIsGPolygon == null) ? false : bIsGPolygon;

	var numberPolygons = currentMultiPolygons.length;

	if (!bIsGPolygon) {
		if (fill) {
			var polygon = new GPolygon(polygon, borderColour, 2, 1, fillColour, 0.15);
		} else {
			var polygon = new GPolygon(polygon, borderColour, 2, 1);
		}
	}

	// if the polygon is persistant don't keep track of it
	if (bPersistant) {

		map.addOverlay(polygon);

	} else {

		currentMultiPolygons[numberPolygons] = polygon;
		map.addOverlay(currentMultiPolygons[numberPolygons]);

	}

}


function removeMultiPolygon() {

	for (var i = 0; i < currentMultiPolygons.length; i++) {
		if(currentMultiPolygons[i] != undefined) {
			map.removeOverlay(currentMultiPolygons[i]);
		}
	}

	currentMultiPolygons = new Array();

}


/**
* Get the outer bounds of an array of Google polygons
*
* @param array of GPolygons
* @return object GBounds
*/
function getMultiPolygonBounds(aPolygons) {

	var aBounds = new Array();

	for (var i=0; i < aPolygons.length; i++) {
		aBounds[i] = aPolygons[i].getBounds();
	}

	for (var j=0; j < aBounds.length; j++) {

		var swLatLng = aBounds[j].getSouthWest();
		var neLatLng = aBounds[j].getNorthEast();

		if (j == 0) {

			var minLat = swLatLng.lat();
			var minLng = swLatLng.lng();

			var maxLat = neLatLng.lat();
			var maxLng = neLatLng.lng();

		} else {

			if(swLatLng.lat() < minLat) {
				minLat = swLatLng.lat();
			}

			if(swLatLng.lng() < minLng) {
				minLng = swLatLng.lng();
			}

			if(neLatLng.lat() > maxLat) {
				maxLat = neLatLng.lat();
			}

			if(neLatLng.lng() > maxLng) {
				maxLng = neLatLng.lng();
			}

		}

	}

	var sw = new GLatLng(minLat, minLng);
	var ne = new GLatLng(maxLat, maxLng);

	return new GLatLngBounds(sw, ne);

}


/**
 * Zoom to outer bounds of a group of polygons
 * @param array optional array of polygons
 * @param boolean optional flag that indicates if the passed in array contains polygon points or GPolygons (default is false)
 *
 */
function zoomToMultiPolygon(aMultiPolygonShape, bGPolygons) {

	var bGPolygons = (bGPolygons == undefined) ? false : bGPolygons;

	// if nothing is passed in then we will use the current multipolygon that has been drawn on the screen
	if (aMultiPolygonShape == undefined) {

		var bounds = getMultiPolygonBounds(currentMultiPolygons);

	} else {

		var aPolygons = new Array();

		if (!bGPolygons) {

			// we need to loop through the array of polygon shapes and create GPolygons
			for (i = 0; i < aMultiPolygonShape.length; i++) {

				aPolygons.push(new GPolygon(aMultiPolygonShape[i]));

			}

		} else {
			aPolygons = aMultiPolygonShape;
		}

		var bounds = getMultiPolygonBounds(aPolygons);

	}

	var centerPoint = bounds.getCenter();
	var zoomLevel = map.getBoundsZoomLevel(bounds);
	map.setCenter(centerPoint, zoomLevel);

}


/*
* Call generic wms service for GoogleMaps v2
* John Deck, UC Berkeley
* Inspiration & Code from:
*	Mike Williams http://www.econym.demon.co.uk/googlemaps2/ V2 Reference & custommap code
*	Brian Flood http://www.spatialdatalogic.com/cs/blogs/brian_flood/archive/2005/07/11/39.aspx V1 WMS code
*	Kyle Mulka http://blog.kylemulka.com/?p=287  V1 WMS code modifications
*      http://search.cpan.org/src/RRWO/GPS-Lowrance-0.31/lib/Geo/Coordinates/MercatorMeters.pm
*
* Modified by Chris Holmes, TOPP to work by default with GeoServer.
* Modified by Eduin Yesid Carrillo Vega to work with any map name.
*
* Note this only works with gmaps v2.36 and above.  http://johndeck.blogspot.com
* has scripts
* that do the same for older gmaps versions - just change from 54004 to 41001.
*
* About:
* This script provides an implementation of GTileLayer that works with WMS
* services that provide epsg 41001 (Mercator).  This provides a reasonable
* accuracy on overlays at most zoom levels.  It switches between Mercator
* and Lat/Long at the myMercZoomLevel variable, defaulting to MERC_ZOOM_DEFAULT
* of 5.  It also performs the calculation from a GPoint to the appropriate
* BBOX to pass the WMS.  The overlays could be more accurate, and if you
* figure out a way to make them so please contribute information back to
* http://docs.codehaus.org/display/GEOSDOC/Google+Maps.  There is much
* information at:
* http://cfis.savagexi.com/articles/2006/05/03/google-maps-deconstructed
*
* Use:
* This script is used by creating a new GTileLayer, setting the required
* and any desired optional variables, and setting the functions here to
* override the appropriate GTileLayer ones.
*
* At the very least you will need:
* var myTileLayer= new GTileLayer(new GCopyrightCollection(""),1,17);
*     myTileLayer.myBaseURL='http://yourserver.org/wms?'
*     myTileLayer.myLayers='myLayerName';
*     myTileLayer=CustomGetTileUrl
*
* After that you can override the format (myFormat), the level at
* which the zoom switches (myMercZoomLevel), and the style (myStyles)
* - be sure to put one style for each layer (both are separated by
* commas).  You can also override the Opacity:
*     myTileLayer.myOpacity=0.69
*     myTileLayer.getOpacity=customOpacity
*
* Then you can overlay on google maps with something like:
* var layer=[G_SATELLITE_MAP.getTileLayers()[0],tileCountry];
* var custommap = new GMapType(layer, G_SATELLITE_MAP.getProjection(), "WMS");
* var map = new GMap(document.getElementById("map"));
*     map.addMapType(custommap);
*/

var PROXY_HOST_MULTIPLE_DOMAIN = false;

var MAGIC_NUMBER = 6378137.0;
var PI = 3.14159265358979323846;

// Enable/disable meta tiling
var META_TILING = true;

//Default image format, used if none is specified
var FORMAT_DEFAULT = "image/png";

//EPSG code with the Google projection definition
var EPSG_GOOGLE_CODE = "EPSG:900913";

var MERC_ZOOM_DEFAULT = 15;
function dd2MercMetersLng(p_lng) {
	return MAGIC_NUMBER * p_lng;
}

function dd2MercMetersLat(p_lat) {
	if (p_lat >= 85) p_lat=85;
	if (p_lat <= -85) p_lat=-85;
	return MAGIC_NUMBER * Math.log(Math.tan(p_lat / 2 + PI / 4));
}

CustomGetTileUrl=function(a,b,c) {

	if (this.myFormat == undefined) {
		this.myFormat = FORMAT_DEFAULT;
	}

	if (this.myMapname == undefined) {
		this.myMapname = "map";
	}

	if (typeof(window['this.myStyles'])=="undefined") this.myStyles="";
	var lULP = new GPoint(a.x*256.0,(a.y+1)*256.0);
	var lLRP = new GPoint((a.x+1)*256.0,a.y*256.0);
	var lUL = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lULP,b,c);
	var lLR = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lLRP,b,c);
	// set a fixed position as the tiles origin for the on the fly meta tiler (0,0) should be good
	var lLL = G_NORMAL_MAP.getProjection().fromPixelToLatLng(new GPoint(0,0), b, c);

	// switch between Mercator and DD if merczoomlevel is set
	eval("var lwz = "+ this.myMapname + ".getZoom()");
	var lBbox= dd2MercMetersLng(lUL.lngRadians())+","+dd2MercMetersLat(lUL.latRadians())+","+dd2MercMetersLng(lLR.lngRadians())+","+dd2MercMetersLat(lLR.latRadians());
	var url = this.myBaseURL;
	// there are multiple domains available, adjust the baseURL
	// this should only be on for the vumap subdomain
	if (PROXY_HOST_MULTIPLE_DOMAIN) {
		var randomHostNumber = ((a.x + a.y) % 4);
		url = this.myBaseURL.replace('http://vumap.', 'http://ts' + randomHostNumber + '.');
	}
	
	var lURL = url;
	lURL += "&LAYERS=" + this.myLayers;
	
	lURL+="&BBOX="+lBbox;
	
	lURL+="&layerId="+this.layerId;
			
	var tileBounds = lUL.lng()+","+lUL.lat()+","+lLR.lng()+","+lLR.lat();	
	lURL += "&tbStr="+tileBounds;		
	
	return lURL;
	
}

function customOpacity() {
	return this.myOpacity;
}

