api_version = FindGoogleAPIVersion();

if (!self.marker_link_target) { marker_link_target = (self.marker_link_target) ? marker_link_target : '_blank'; } // BC
if (!self.maptypecontrol_style) { maptypecontrol_style = (self.maptypecontrol_style) ? maptypecontrol_style : 'menu'; } // BC
if (self.filter_map_types==null) { filter_map_types = (self.filter_map_types!=null) ? filter_map_types : true; }
if (!self.icon_directory) { icon_directory = 'http://maps.gpsvisualizer.com/google_maps/icons/'; }
if (self.driving_directions==null) { driving_directions = false; }
/**************************************************
 * Custom map layers:
 * Adapted from Jef Poskanzer's Acme Mapper
 * (http://mapper.acme.com/)
 **************************************************/
if (api_version >= 2) {
	var USGS_TOPO_TILES = WMSCreateMap('Topo','Topo maps by USGS via terraserver-usa.com','Topo maps unavailable',5,17,400,'http://terraservice.net/ogcmap6.ashx?version=1.1.1&request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&bgcolor=0xCCCCCC&exceptions=INIMAGE&layers=DRG');
	var USGS_AERIAL_TILES = WMSCreateMap('Aerial','Imagery by USGS via terraserver-usa.com','USGS aerial imagery unavailable',7,18,400,'http://terraservice.net/ogcmap6.ashx?version=1.1.1&request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&bgcolor=0xCCCCCC&exceptions=INIMAGE&layers=DOQ');
	var NRCAN_TOPO_TILES = WMSCreateMap('NRCan','Maps by NRCan.gc.ca','NRCan maps unavailable',6,18,600,'http://wms.cits.rncan.gc.ca/cgi-bin/cubeserv.cgi?version=1.1.3&request=GetMap&format=image/png&bgcolor=0xFFFFFF&exceptions=application/vnd.ogc.se_inimage&srs=EPSG:4326&layers=PUB_50K:CARTES_MATRICIELLES/RASTER_MAPS');
	var NRCAN_TOPO_NAMES_TILES = WMSCreateMap('NRCan+','Maps by NRCan.gc.ca','NRCan maps unavailable',11,18,600,'http://wms.cits.rncan.gc.ca/cgi-bin/cubeserv.cgi?version=1.1.3&request=GetMap&format=image/png&bgcolor=0xFFFFFF&exceptions=application/vnd.ogc.se_inimage&srs=EPSG:4326&layers=PUB_50K:CARTES_MATRICIELLES/RASTER_MAPS,TOPONYME_0:BNDT_50K/NTDB_50K');
	var LANDSAT_TILES = WMSCreateMap('Landsat','Map by NASA','OnEarth server unavailable',3,15,256,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=global_mosaic');
	var BLUEMARBLE_TILES = WMSCreateMap('BlueMarble','Map by NASA','OnEarth server unavailable',3,8,128,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=modis');
	var DAILY_TERRA_TILES = WMSCreateMap('"Terra"','Map by NASA','OnEarth server unavailable',3,10,256,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=daily_terra');
	var DAILY_AQUA_TILES = WMSCreateMap('"Aqua"','Map by NASA','OnEarth server unavailable',3,10,256,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=daily_aqua');
}

function Add_Custom_Layers(map) {
	map.addMapType(USGS_TOPO_TILES);
	map.addMapType(USGS_AERIAL_TILES);
	map.addMapType(NRCAN_TOPO_TILES);
	map.addMapType(NRCAN_TOPO_NAMES_TILES);
	map.addMapType(LANDSAT_TILES);
	map.addMapType(BLUEMARBLE_TILES);
	map.addMapType(DAILY_TERRA_TILES);
	map.addMapType(DAILY_AQUA_TILES);
}


function WMSCreateMap(name,copyright,errorMessage,minResolution,maxResolution,tileSize,baseUrl) {
	var tileLayer = new GTileLayer(new GCopyrightCollection(copyright),minResolution,maxResolution);
	tileLayer.baseUrl = baseUrl;
	tileLayer.tileSize = tileSize;
	tileLayer.getTileUrl = WMSGetTileUrl;
	tileLayer.getCopyright = function() { return { prefix:'',copyrightTexts:[copyright]}; };
	var tileLayers = [tileLayer];
	return new GMapType(tileLayers,G_SATELLITE_MAP.getProjection(),name,{errorMessage:errorMessage,tileSize:tileSize});
}
function WMSGetTileUrl(tile,zoom) {
	var southWestPixel = new GPoint(tile.x*this.tileSize,(tile.y+1)*this.tileSize);
	var northEastPixel = new GPoint((tile.x+1)*this.tileSize,tile.y*this.tileSize);
	var southWestCoords = G_SATELLITE_MAP.getProjection().fromPixelToLatLng(southWestPixel,zoom);
	var northEastCoords = G_SATELLITE_MAP.getProjection().fromPixelToLatLng(northEastPixel,zoom);
	var bbox = southWestCoords.lng()+','+southWestCoords.lat()+','+northEastCoords.lng()+','+northEastCoords.lat();
	return this.baseUrl+'&bbox='+bbox+'&width='+this.tileSize+'&height='+this.tileSize;
}



function Place_Control(map,control_id,anchor,x,y) {
	if (document.getElementById(control_id)) {
		document.getElementById(control_id).style.display = 'block';
		var position = new GControlPosition(anchor, new GSize(x,y));
		position.apply(document.getElementById(control_id));
		map.getContainer().appendChild(document.getElementById(control_id));
	}
}

/**************************************************
 * Custom map-type control:
 * more or less from Google's own documentation
 **************************************************/
function MapTypeControl() {}
if (api_version >= 2) {
	MapTypeControl.prototype = new GControl();
	MapTypeControl.prototype.getDefaultPosition = function() {
		return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,7));
	}
	MapTypeControl.prototype.initialize = function(map) {
		Add_Custom_Layers(map);
		var map_types = [
			{ label:'G. map',type:'G_NORMAL_MAP',title:'Google street map',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'G. satellite',type:'G_SATELLITE_MAP',title:'Google satellite map',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'G. hybrid',type:'G_HYBRID_MAP',title:'Google "hybrid" map',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'USGS topo',type:'USGS_TOPO_TILES',title:'USGS topographic map',bounds:[-169,18,-66,72],excluded:[],country:'us' }
			,{ label:'USGS aerial',type:'USGS_AERIAL_TILES',title:'USGS aerial photos (black/white)',bounds:[-152,17,-65,65],excluded:[],country:'us' }
			,{ label:'Canada topo',type:'NRCAN_TOPO_TILES',title:'NRCan/Toporama maps with contour lines',bounds:[-141,41.7,-52,85],excluded:[-141,41.7,-86,48],country:'ca' }
			,{ label:'Can. topo+names',type:'NRCAN_TOPO_NAMES_TILES',title:'NRCan/Toporama topo maps with feature names',bounds:[-141,41.7,-52,85],excluded:[-141,41.7,-86,48],country:'ca' }
			,{ label:'Landsat 30m',type:'LANDSAT_TILES',title:'NASA Landsat 30-meter imagery',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'Blue Marble',type:'BLUEMARBLE_TILES',title:'NASA "Visible Earth" image',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'Daily "Terra"',type:'DAILY_TERRA_TILES',title:'Daily imagery from "Terra" satellite',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'Daily "Aqua"',type:'DAILY_AQUA_TILES',title:'Daily imagery from "Aqua" satellite',bounds:[-180,-90,180,90],excluded:[] }
		];
		if (self.custom_map_types && custom_map_types.length > 0) {
			for (j=0; j<custom_map_types.length; j++) { map_types.push(custom_map_types[j]); }
		}
		var center_lat = map.getCenter().lat();
		var center_lng = map.getCenter().lng();
		
		var excluded_maps = new Array;
		if (self.filter_map_types && filter_map_types && self.excluded_map_types && excluded_map_types) {
			for (j=0; j<excluded_map_types.length; j++) {
				excluded_maps[excluded_map_types[j]] = true;
			}
		}
		for (j=0; j<map_types.length; j++) {
			if (self.country && country) {
				if (map_types[j]['country'] && map_types[j]['country'].indexOf(country) < 0) {
					excluded_maps[map_types[j]['type']] = true;
				}
			} else {
				if (!(center_lng >= map_types[j]['bounds'][0] && center_lat >= map_types[j]['bounds'][1] && center_lng <= map_types[j]['bounds'][2] && center_lat <= map_types[j]['bounds'][3]) || (center_lng >= map_types[j]['excluded'][0] && center_lat >= map_types[j]['excluded'][1] && center_lng <= map_types[j]['excluded'][2] && center_lat <= map_types[j]['excluded'][3]) ) {
					excluded_maps[map_types[j]['type']] = true;
				}
			}
		}
		if (maptypecontrol_style == 'menu') {
			var map_selector = document.createElement("select");
			map_selector.id = 'map_selector';
			map_selector.style.font = '10px Verdana';
			map_selector.style.backgroundColor = '#FFFFFF';
			for (j=0; j<map_types.length; j++) {
				if (!filter_map_types || !excluded_maps[map_types[j]['type']]) {
					var opt = document.createElement("option");
					opt.value = map_types[j]['type'];
					opt.appendChild(document.createTextNode(map_types[j]['label']));
					map_selector.appendChild(opt);
					if (map.getCurrentMapType() == eval(opt.value)) { map_selector.selectedIndex = map_selector.length - 1; }
				}
			}
			GEvent.addDomListener(map_selector, "change", function(){
				map.setMapType(eval(this.value));
				// if (self.maptypecontrol) {
				// 	map.removeControl(maptypecontrol);
				// 	map.addControl(maptypecontrol);
				// }
			} );
			map.getContainer().appendChild(map_selector);
			return map_selector;
		} else { // 'list'
			var map_type_container = document.createElement("div");
			for (j=0; j<map_types.length; j++) {
				var map_ok = true;
				if (filter_map_types && !(center_lng >= map_types[j]['bounds'][0] && center_lat >= map_types[j]['bounds'][1] && center_lng <= map_types[j]['bounds'][2] && center_lat <= map_types[j]['bounds'][3]) || (center_lng >= map_types[j]['excluded'][0] && center_lat >= map_types[j]['excluded'][1] && center_lng <= map_types[j]['excluded'][2] && center_lat <= map_types[j]['excluded'][3]) ) { map_ok = false; }
				if (self.country && country && map_types[j]['country'] && map_types[j]['country'].indexOf(country) < 0) { map_ok = false; }
				if (excluded_maps[map_types[j]['type']]) { map_ok = false; }
				if (map_ok) {
					var maplink = document.createElement("div");
					maplink.className = 'maptypelink';
					if (self.maptypecontrol && map.getCurrentMapType() == eval(map_types[j]['type'])) {
						maplink.className = 'maptypelink maptypelink_selected';
					}
					maplink.title = map_types[j]['title'];
					maplink.type = map_types[j]['type'];
					map_type_container.appendChild(maplink);
					maplink.appendChild(document.createTextNode(map_types[j]['label']));
					GEvent.addDomListener(maplink, "click", function(){
						map.setMapType(eval(this.type));
						if (self.maptypecontrol) {
							map.removeControl(maptypecontrol);
							map.addControl(maptypecontrol);
						}
					} );
				}
			}
			map.getContainer().appendChild(map_type_container);
			return map_type_container;
		}
	}
}



function FindGoogleAPIVersion() {
	var v = 2;
	var scripts = document.getElementsByTagName("script")
	for (var i=0; i<scripts.length; i++) {
		var pattern = /\/maps([0-9])?(\.?[0-9]+)(\.api)?\.js/;
		var m = pattern.exec(scripts[i].src);
		if (m != null) {
			if (m[1] == null) { v = parseFloat('1'+m[2]); }
			else { v = parseFloat(m[1]+m[2]); }
			break;
		}
	}
	return v;
}

function Filter_Tracks (map,info) {
	if (info == null || info == undefined || !info.length) { return false; }
	var min_lat = map.getBounds().getSouthWest().lat();
	var min_lon = map.getBounds().getSouthWest().lng();
	var max_lat = map.getBounds().getNorthEast().lat();
	var max_lon = map.getBounds().getNorthEast().lng();
	if (max_lon < min_lon) { min_lon = -180; max_lon = 180; } // Date Line weirdness
	for (var t in info) {
		if (info[t]['e'] < min_lon || info[t]['w'] > max_lon || info[t]['n'] < min_lat || info[t]['s'] > max_lat) {
			Track_OutOfRange(map,eval(t),true);
		} else {
			Track_OutOfRange(map,eval(t),false);
		}
	}
}
function Track_OutOfRange (map,trk_array,is_oor) {
	if (is_oor) {
		if (!trk_array.hidden) { // if it's already hidden, there's nothing to do
			for (j=0; j<trk_array.length; j++) { map.removeOverlay(trk_array[j]); }
		}
		trk_array.oor = true;
	} else {
		if (trk_array.oor) { // only add it if it was previously out of range
			if (!trk_array.hidden) { // if it's supposed to be hidden, don't show it
				for (j=0; j<trk_array.length; j++) { map.addOverlay(trk_array[j]); }
			}
		}
		trk_array.oor = false;
	}
}



/**************************************************
 * dom-drag.js
 * 09.25.2001
 * www.youngpup.net
 * Script featured on Dynamic Drive (http://www.dynamicdrive.com) 12.08.2005
 **************************************************
 * 10.28.2001 - fixed minor bug where events
 * sometimes fired off the handle, not the root.
 **************************************************/
var Drag = {

	obj : null,

	init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) {
		if (!o) { return false; }
		o.onmousedown	= Drag.start;

		o.hmode			= bSwapHorzRef ? false : true ;
		o.vmode			= bSwapVertRef ? false : true ;

		o.root = oRoot && oRoot != null ? oRoot : o ;

		if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
		if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;

		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;

		o.root.onDragStart	= new Function();
		o.root.onDragEnd	= new Function();
		o.root.onDrag		= new Function();
	},

	start : function(e) {
		var o = Drag.obj = this;
		e = Drag.fixE(e);
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		o.root.onDragStart(x, y);

		o.lastMouseX	= e.clientX;
		o.lastMouseY	= e.clientY;

		if (o.hmode) {
			if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
			if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
		} else {
			if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
			if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
		}

		if (o.vmode) {
			if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
			if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
		} else {
			if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
			if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
		}
		
		onmousemove_before_dragging = document.onmousemove; // preserve this and put it back later
		onmouseup_before_dragging = document.onmouseup; // preserve this and put it back later
		document.onmousemove	= Drag.drag;
		document.onmouseup		= Drag.end;

		return false;
	},

	drag : function(e) {
		e = Drag.fixE(e);
		var o = Drag.obj;

		var ey	= e.clientY;
		var ex	= e.clientX;
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		var nx, ny;

		if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
		if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
		if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
		if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

		if (o.xMapper)		nx = o.xMapper(y)
		else if (o.yMapper)	ny = o.yMapper(x)

		Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
		Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
		Drag.obj.lastMouseX	= ex;
		Drag.obj.lastMouseY	= ey;

		Drag.obj.root.onDrag(nx, ny);
		return false;
	},

	end : function() {
		// document.onmousemove = null;
		// document.onmouseup   = null;
		document.onmousemove = (self.onmousemove_before_dragging) ? onmousemove_before_dragging : null;
		document.onmouseup = (self.onmouseup_before_dragging) ? onmouseup_before_dragging : null;
		Drag.obj.root.onDragEnd(	parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
									parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
		Drag.obj = null;
	},

	fixE : function(e) {
		if (typeof e == 'undefined') e = window.event;
		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
		return e;
	}
};



function IE_PNG() { // correctly handle PNG transparency in Win IE 5.5 & 6.
	var arVersion = navigator.appVersion.split("MSIE")
	var version = parseFloat(arVersion[1])
	if ((version >= 5.5) && (document.body.filters)) {
		for(var i=0; i<document.images.length; i++) {
			var img = document.images[i]
			var imgName = img.src.toUpperCase()
			if (imgName.substring(imgName.length-3, imgName.length) == "PNG") {
				var imgID = (img.id) ? "id='" + img.id + "' " : "";
				var imgClass = (img.className) ? "class='" + img.className + "' " : "";
				var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
				var imgStyle = "display:inline-block;" + img.style.cssText;
				if (img.align == "left") { imgStyle = "float:left;" + imgStyle; }
				if (img.align == "right") { imgStyle = "float:right;" + imgStyle; }
				if (img.parentElement.href) { imgStyle = "cursor:hand;" + imgStyle; }
				var strNewHTML = "<span " + imgID + imgClass + imgTitle
				  + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
				  + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
				  + "(src=\'" + img.src + "\', sizingMethod='image');\"></span>" ;
				img.outerHTML = strNewHTML;
				i = i-1;
			}
		}
	}
}
