/**
  * (c) SMARTposition 2006-2007
  *
  * http://www.smartposition.nl
  * 
  * date: 26 june 2007
  * version: 0.6
  * -----------------
  * 0.1		basic functions
  * 0.2		more options
  * 0.3		added centering
  * 0.4		added info divs
  * 0.5 	imporovement on GPX parsing
  * 0.6 	added dynamic KML overlays and some overall improvements
  *
  *
  * BUGS
  * -
  */

/*
 * initial map parameters
 */
var mapSize = "large";
var mapType = G_NORMAL_MAP; //G_HYBRID_MAP; //G_SATELLITE_MAP;
var zoomLevel = 10;
var initialLat = 52.281634;
var initialLong = 6.421701;

var baseIcon = new GIcon();
      baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
      baseIcon.iconSize = new GSize(20, 34);
      baseIcon.shadowSize = new GSize(37, 34);
      baseIcon.iconAnchor = new GPoint(9, 34);
      baseIcon.infoWindowAnchor = new GPoint(9, 2);
      baseIcon.infoShadowAnchor = new GPoint(18, 25);


/**
  * GPX parameters
  */
var gpxUrl = "./gpx.php";
var tailLength = 20;							//GPX request parameter
var trackStart = 20070101120159;				//GPX request parameter

var refreshInterval = 15 * 1000;
var reloadPageInterval = 1000* 60 * 15;

/*
 * marker drawing parameters
 */
var iconTable = createIcons();

var drawWaypoints = true;
var waypointMarkerIcon = iconTable["red_pin"];
var drawRoutes = true;
var drawRoutePolyLine = true;
var drawTracks = true;
var drawTrackPolyLine = true;
var initCustomMap = true;

/*
 * Audio parameters
 */
var speedAudioFile = '';
var speedAudioRepeat = '1';

// route/track drawing parameters
var drawStartMarker = false; // draw marker at the start of a route/track
var startMarkerIcon = iconTable["flag_green.png"];
var drawEndMarker = true; // draw marker at the end of a route/track
var endMarkerIcon = iconTable["flag_red.png"];
var drawIntervalMarker = 1; // for routes and tracks, draw markers at the specified interval on the polyline; int
var intervalMarkerIcon = iconTable["dot_12_009cff.png"];

/*
 * Centering options
 */
var autoCenter = false; // value is overwritten at init in functions.js/init()
var routeDisplay = true;
var focusOn = "351277002680576";
var focusInfo = new Array();
var isCentered = false;
var minimalCenterMovement=0.20;
var minimalTrackerSpeed = 0;	//km/h
var maximalTrackerSpeed = 200;	//km/h
var audioAlarm = false;	
var audioAlarmTimeout = 1;

//map object
var map = null;

var mapOverlays = new Array();

//geoXML object to parse a KML into GMaps
var geoXml = new Array();
var customerLogoSrc = '';


//variable that holds the kml file with distance information
var useGeoXmlDistance = false;
var geoXmlDistance;

//sets the init for the KML layer
var initGeoXml = true; 

/**
  * Function to initialize the google earth map
  *
  */
function initMap(id){
	if (!GBrowserIsCompatible()) {
		alert('Your browser is not compatible with the Google Maps API, please install the latest version of your webbrowser!');
		return;
	}
	
	//start the clock
	setInterval('updateClock(eventStartDate)',1000);
	
	//change images
	if(customerLogoSrc != ''){
		document.getElementById("customerLogo").style.display = 'block';
		document.getElementById("customerLogoImg").src = customerLogoSrc;
	}//end set custom logo

	map = new GMap2(document.getElementById(id));
	
	// Add the custom map
	addcustomMap();
	
	// Add the custom opacity maps
	//addcustomMapOpacity();
	
	
	if (this.mapSize == "small") {
		map.addControl(new GSmallMapControl());
	}else {
		//Add map controls
		map.addControl(new GMapTypeControl());
		map.addControl(new GLargeMapControl(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,45)));
	}//end if mapSize
	
	// Enable map control properties
	map.enableInfoWindow();
	map.enableDragging();
	map.enableDoubleClickZoom();
	map.enableContinuousZoom();	
	map.enableScrollWheelZoom();
	
	//add map listeners
	GEvent.addListener(map, "moveend", function() {
	  var center = map.getCenter();
	  initialLat = center.lat();
	  initialLong = center.lng();
	});
	
	GEvent.addListener(map, "zoomend", function(oldLevel, newLevel) {
		//record the zoom level for auto refreshing
	 	zoomLevel = newLevel;
	});
	
	GEvent.addListener(map, "maptypechanged", function() {
	});
	
	
	
	zoomLevel = parseInt(zoomLevel);	//otherwise the zoomLevel will be set to 0
	
	// Set center
	map.setCenter(new GLatLng(initialLat, initialLong), zoomLevel, mapType);
	
	
	//add kml overlay files
	addKmlOverlay();
}//end initMap

/**
  * Loads the map in view only mode
  */
function loadViewMap(id, mapSize) {
	if (mapSize) this.mapSize = mapSize;
	
	initMap(id);
	
}//end function loadViewMap


/**
 * Initialize data on gmaps loaded from a GPX file
 *
 * @param data
 * @param responseCode
 *
 * @return null
 */
function onGPXLoad(data, responseCode) {
	
	var xml = GXml.parse(data);
	var gpx = new GPX();
	
	if (responseCode == 200) gpx.load(xml);
	else setStatus("Sorry, the GPX file could not be loaded");
	
	
	//remove all overlays (except the geoXml)
	var tmpOverlay;
	while(tmpOverlay = (mapOverlays.pop())){
		map.removeOverlay(tmpOverlay);
	}//end remove mapOverlays
	
	mapOverlays = new Array();
	
	
	
	// Draw waypoints
	if (drawWaypoints) {
		var waypoints = gpx.getWaypoints();
		var html = "";
		for (var i = 0; i < waypoints.length; i++) {
			wpt = waypoints[i];
			
			markerIcon = chooseIcon(GPX.wpt, "", wpt.sym);
			html = "<b>"+wpt.name+"</b>";
			if(wpt.cmt){
				html += "<br />" + wpt.cmt;
			}//end comment
			
			createMarker(wpt, html, markerIcon);
		}//end for
	
	}//end drawWaypoints
	
	// Draw tracks
	if (drawTracks) {
		var tracks = gpx.getTracks();
		
		centerView(GPX.trk, tracks);
		
		// Iterate through tracks
		for (var i = 0; i < tracks.length; i++) {
			if (tracks[i]) {
				
				// Iterate through track segments
				for (var s = 0; s < tracks[i].length; s++) {
					if (tracks[i][s]) {
						drawSequence(GPX.trk, tracks[i][s], tracks[i].name,tracks[i].desc,tracks[i].color);
					}//end if
				}//end for
			}//end if
		}//end for
	}//end draw tracks
	
	// Draw routes
	if (drawRoutes) {
		var routes = gpx.getRoutes();
		
		//centerView(GPX.rte, routes);
		
		// Iterate through routes
		for (var i = 0; i < routes.length; i++) {
			if (routes[i]) {
				drawSequence(GPX.rte, routes[i], routes[i].name,tracks[i].desc,tracks[i].color);
			}//end if
		}//end for
	}//end drawroutes
	
	if(useGeoXmlDistance && geoXmlDistance){
		map.removeOverlay(geoXmlDistance);
		// add KML overlay
		map.addOverlay(geoXmlDistance);
	}
	
	
	/* set Timeout to reload GPX data!! */
	window.setTimeout('loadData()', refreshInterval);
}//end function onGPXLoad

/*
 * Function that centers the map on the value of the variable "focusOn".
 * Also, the last position (and it's associated information) for each track is put
 * into the "focusInfo" array. Part of this information is also put in the DOM
 * as a div element, into the "focusInfo" div.
 *
 * @param type
 * @param tracks
 * 
 * @return null
 */
function centerView(type, tracks) {
	clearChildren(document.getElementById("focusInfo"));
	
	var today_date = new Date();
	
	// loop through the tracks and check if it actually contains tracksegments
	for (var i = 0; i < tracks.length; i++) {
		if (tracks[i] && tracks[i].length > 0) {
			
			var infoNode = document.createElement("div");
			infoNode.id = tracks[i].name;
			
			infoNode.className = "info";
			document.getElementById("focusInfo").appendChild(infoNode);
			
			lastSeg = tracks[i].length - 1;
			
			if (tracks[i][lastSeg].length > 0) {
				lastPoint = 0;//tracks[i][lastSeg].length - 1;

				focusInfo[tracks[i].name] = tracks[i][lastSeg][lastPoint];
				focusInfo[tracks[i].name].focusLink = "<a href='javascript:void(0)' onclick='setFocus(" + tracks[i].name + ")' title=''><span style='display: %s;'>%s</span></a>";
				
				var current = focusInfo[tracks[i].name];
				
				
				var print_time = current.time.replace('T',' ').replace('Z','');
				var position_time = parseXmlTimeToDate(print_time);
				
				var speedingClass = '';
				//check the speed of the tracker
				if(current.speed){
					if(current.speed < minimalTrackerSpeed){
						speedingClass='minSpeed';
						if(audioAlarm && (calculateTimeDeltaMinutes(position_time,today_date) < audioAlarmTimeout)){
							soundManager.play(speedAudioFile,speedAudioRepeat);
						}//end audio alarm
						
					}else if(current.speed > maximalTrackerSpeed){
						speedingClass='maxSpeed';
						if(audioAlarm && (calculateTimeDeltaMinutes(position_time,today_date) < audioAlarmTimeout)){
							soundManager.play(speedAudioFile,speedAudioRepeat);
						}//end audio alarm
					}
					//use default
				}//end speed check
				
				// format the displayed time
				if((today_date.getDate()) ==  position_time.getDate() && (today_date.getMonth()) == position_time.getMonth()){
					print_time = print_time.substring(11) + " (today)";
				}
				
				var infoNodeContent = "<h2 class='title "+speedingClass+"'><div class='color' style='background-color: #" + tracks[i].color + ";'></div>"
										+ tracks[i].desc + current.focusLink + "</h2>" +
										"<div style='display: %s;'>" +
										"<p class='date'><span class='key'>Time:</span><span class='value'>" +
										current.time.replace('T',' ').replace('Z','').substring(11) + 
										"</span></p>";
				if(current.speed){
					infoNodeContent += "<p class='speed '><span class='key'>Speed:</span><span class='value "+speedingClass+"'>" + current.speed + " km/h</span></p>";
				}//end speed append
				
				if(current.distance && current.distance > 0){
					infoNodeContent += "<p class='speed'><span class='key'>Remaining:</span><span class='value'>" + current.distance + " km</span></p>";
				}//end speed append
				
										
				if(current.cmt){
					infoNodeContent += "<p class='course'><span class='key'>Geofence:</span><span class='value'>" +  current.cmt + "</span></p>";
				}//end desc append
				
				if(current.info_name){
					infoNodeContent += "<p class='link'><span class='key'>Info:</span><span class='value'>";
					if(current.link) { infoNodeContent += "<a href='" + current.link + "' target='_blank'>" + current.info_name + "</a>"; }
					else { infoNodeContent += current.info_name; }
					infoNodeContent += "</span></p>";
				}//end speed append
				
				if(!getRequestParams()['history']){
					//infoNodeContent += "<p class='course'><span class='value'><a href='./?geodata=gpx.php?id="+tracks[i].name+"&history=100'> Show history</a></span></p>";
				}//end history link
			
				infoNodeContent 	+= "</div>";
				
				// show information for focused object
				if (tracks[i].name == focusOn) {
					infoNode.innerHTML = printf(infoNodeContent, "inline", "volgen", "block");

					// has the centered point moved more than 15% from the center of the map?
					if (autoCenter && (getPercentageFromCenter(tracks[i][lastSeg][lastPoint]) > minimalCenterMovement)) {
						map.setCenter(current);
					}
					isCentered = true;
				}
				// if this track is not focused, just show the title
				else {
					infoNode.innerHTML = printf(infoNodeContent, "inline", "volgen",  "none")
				}
			}
		}
	}//end tracks forloop
	
	return true;
}//end function centerView

/*
 * Draws the actual routes and tracks on top of the map
 *
 * @param type
 * @param sequence
 * @param name
 * @description
 * @color
 *
 * @return null
 */
function drawSequence(type, sequence, name, description, color) {
	if (sequence.length > 0) {
		// Draw route as polyline
		if ((type == GPX.rte && drawRoutePolyLine) || (type == GPX.trk && drawTrackPolyLine)) {
			lineStyle = chooseLineStyle(type, name, color);
			var line = new GPolyline(sequence, lineStyle.color, lineStyle.width, lineStyle.opacity);
			
			addOverlay(line,true);
			
		}//end polyLine
		
		// Draw 1 in drawIntervalMarker waypoints as a marker
		if (drawIntervalMarker) {
			var startCount = drawStartMarker ? drawIntervalMarker : 0;
			var endCount = drawEndMarker ? sequence.length : (sequence.length + 1);
			
			for (var w = startCount; w < endCount; w += drawIntervalMarker) {
				wpt = sequence[w];
				
				html = "<div class='markerInfo'><h2 class='name'>" + description + "</h2>"
										+ "<p class='date'><span class='key'>Time:</span><span class='value'>" +
										wpt.time.replace('T',' ').replace('Z','') + 
										"</span></p>";
				if(wpt.speed){
						html += "<p class='speed'><span class='key'>Speed:</span><span class='value'>" + wpt.speed + " km/h</span></p>";
				}//end speed append

				
				html += "</div>";
			
				markerIcon = chooseIcon(type, "interval", color);
				createMarker(wpt, html, markerIcon);
			}//end for
		}//end interval marker
		
		// Draw first and last marker
		if (drawStartMarker) {
			wpt = sequence[sequence.length-1];
			
			markerIcon = chooseIcon(type, "start", color);
			createMarker(wpt, "<div class='markerInfo'><h2 class='name'>" + description + "</h2>" + wpt.cmt + "</div>", markerIcon);
		}//end startMarkerk
		
		if (drawEndMarker) {
			wpt = sequence[0];
			
			var lnk = "";
			if (wpt.focusLink) {
				lnk = "<p class='focusLink'>" + printf(wpt.focusLink, "inline", "Klik hier om " + description + " te volgen") + "</p>";
			}
			
			markerIcon = chooseIcon(type, "end", wpt.sym+'_'+color);
			html = "<div class='markerInfo'><h2 class='name'>" + description + "</h2>" + lnk 
										+ "<p class='date'><span class='key'>Time:</span><span class='value'>" +
										wpt.time.replace('T',' ').replace('Z','') + 
										"</span></p>";
			if(wpt.speed){
					html += "<p class='speed'><span class='key'>Speed:</span><span class='value'>" + wpt.speed + " km/h</span></p>";
			}//end speed append
			if(wpt.magvar){
					html += "<p class='course'><span class='key'>Course:</span><span class='value'>" +  wpt.magvar + " &deg;</span></p>";
			}//end magvar append
			
			if(wpt.sat){
					html += "<p class='course'><span class='key'>Satellite:</span><span class='value'>" +  wpt.sat + " </span></p>";
			}//end sat append
			
			if(wpt.hdop){
					html += "<p class='course'><span class='key'>DOP:</span><span class='value'>" +  wpt.hdop + " </span></p>";
			}//end hdop append
			
			if(wpt.info_name){
					html += "<p class='course'><span class='key'>Info:</span><span class='value'>" +  wpt.info_name + " </span></p>";
			}//end info_name append
			
			if(wpt.text){
					html += "<p class='course'><span class='value'>" +  wpt.text + " </span></p>";
			}//end text append
			
			if(wpt.image){
					var img = new Image();
					img.src = wpt.image;
					html += "<p class='course'><span class='value'><img src='" +  wpt.image + "' width='" + img.width + "' height='" + img.height + "'/></span></p>";
			}//end text append
			
			
			html += "</div>";
			
			createMarker(wpt,html , markerIcon);
		}//end end marker
	}
}//end function drawSequence

/**
  * Set focus to a specified object
  *
  * @param focusTo
  */
function setFocus(focusTo) {
	
	if(useGeoXmlDistance){
		geoXmlDistance = new GGeoXml("http://194.151.150.217/html/kml.php?imei=" + focusTo);
	}
	
	if (focusTo != focusOn) {
		focusNode = document.getElementById(focusTo);
		
		var infoNodes = focusNode.parentNode.childNodes;
		
		for (var i = 0; i < infoNodes.length; i++) {
			infoNodes[i].getElementsByTagName("div")[1].style.display = "none";
			infoNodes[i].getElementsByTagName("span")[0].style.display = "inline";
		}
		focusNode.getElementsByTagName("div")[1].style.display = "block";
		focusNode.getElementsByTagName("span")[0].style.display = "none";
		
		focusOn = focusTo;
	}

	map.setCenter(focusInfo[focusTo]);
	
	return true;
}//end function setFocus

/**
  * Function creates a marker point with a info window
  *
  * @param point
  * @param html
  * @param icon
  *
  * @return marker
  */
function createMarker(point, html, icon){
	var marker;
	
	if (icon) marker = new GMarker(point,icon);
	else marker = new GMarker(point);
	
	//add event listners
	GEvent.addListener(marker, "dblclick", function() {
		map.setCenter(marker.getPoint());
	});
	
	if (this.mapSize == "large") {
		GEvent.addListener(marker, "click", function() {
			//open window
			marker.openInfoWindowHtml(html);
			//center map to this point
			//map.setCenter(marker.getPoint());
		});
	}
	addOverlay(marker,true);
	
	return marker;
}//end function createMarker

/**
  * Get the percentage of a specified point to the center
  *
  * @param point
  *
  * @return percentage (0.x)
  */
function getPercentageFromCenter(point) {
	mapCrossSize = map.getBounds().getNorthEast().distanceFrom(map.getBounds().getSouthWest());
	mapCenter = map.getCenter();
	if(mapCenter){
		distanceFromCenter = mapCenter.distanceFrom(point);
		//alert(distanceFromCenter/mapCrossSize);
		return distanceFromCenter/mapCrossSize;
	}
	return 0.9;
}//end function getPercentageFromCenter


/**
  * Add item to the maps
  *
  * @param overlay
  * @param isRemovable
  *
  * @return null
  */
function addOverlay(overlay,isRemovable){
	map.addOverlay(overlay);
	if(isRemovable){
		mapOverlays.push(overlay);
	}
}//end function addOverlay

/**
  * Create the tilelayer
  *
  * @return null
  */ 
function addKmlOverlay(){
	if(!initGeoXml && (geoXml.length == 0)) return;
	
	var tmpGeoXml;
	while(tmpGeoXml = (geoXml.pop())){
		addOverlay(tmpGeoXml,false);
	}//end add overlays
}//end function addKmlOverlay

/**
  * Create and ADD the custom map
  *
  * @return null
  */ 
function addcustomMap(){
	if(!initCustomMap) return;

	var copyrightCollection = new GCopyrightCollection('White edition');
	copyrightCollection.addCopyright(new GCopyright(1, new GLatLngBounds(new GLatLng(-90, -180),new GLatLng(90, 180) ),	0, "SMARTposition"));	
		
	var tilelayers = [new GTileLayer(copyrightCollection,1,17)];
	
	tilelayers[0].getTileUrl = function(a,b) {	
		return "http://beta.smartposition.nl/gfx/white_tile.gif";
	}	
	var customMap = new GMapType(tilelayers, new GMercatorProjection(19), 'White',{errorMessage:"No customized map available"});
	
	
	// add the custom map to map
	map.addMapType(customMap);
}//end addcustomMap function
  
/**
  * add custom map with different opacity
  *
  *
  */
function addcustomMapOpacity(){
	if(!initCustomMap) return;

	// Create tile layers
    var tileCountry= new GTileLayer(new GCopyrightCollection(""),1,12);
	
	tileCountry.myFormat='image/gif';	    
  
    tileCountry.myOpacity=0.49;
    tileCountry.getOpacity=function customOpacity() {
	   return this.myOpacity;
	};  

	tileCountry.getTileUrl= function(a,b) {	
		return "http://www.smartposition.nl/holten/tiles/white_tile.gif";
	}

 	var layer3=[G_SATELLITE_MAP.getTileLayers()[0],tileCountry];    
 	var layer2=[G_NORMAL_MAP.getTileLayers()[0],tileCountry];  	
 	
  	var custommap3 = new GMapType(layer3, G_SATELLITE_MAP.getProjection(), "Sat-White", G_SATELLITE_MAP); 
  	var custommap2 = new GMapType(layer2, G_NORMAL_MAP.getProjection(), "Map-White", G_NORMAL_MAP);       
	
	map.addMapType(custommap3);
	map.addMapType(custommap2);
    	
}//end addcustomMapOpacity function

/**
  * function to parse a XML time stamp to javascript date (basic version)
  *
  * @param xmlDate (yyyy-mm-ddThh:mm:ssZ)
  *
  * @return javascript date object 
  *
  */
function parseXmlTimeToDate(xmlDate){
	var date = new Date(xmlDate.substring(0,4),(xmlDate.substring(5,7))-1,xmlDate.substring(8,10),xmlDate.substring(11,13),xmlDate.substring(14,16));
	return date;
}//end function parseXmlTimeToDate

/**
  * function that calculates the difference in minutes between two dates
  *
  */
function calculateTimeDeltaMinutes(date,compareDate){
	return Math.round((compareDate.getTime()-date.getTime())/(1000*60));
}//end function calculateTimeDelta
