
/*
 * This class is used to obtain driving directions results and display them on a map 
 */
function MMDirections(map){	
	this.map = map;  	

	this.waypoints = new Array();
	this.routes = new Array();
	
	this.selectedRoute = null
	
	GEvent.bind(map, "click", this, function(){
		if(this.selectedRoute)
		{
			this.selectedRoute.SetSelection(false);		
			this.selectedRoute = null;

			this.UpdateMenuIcons();
			this.bikeToolWindow.hideWindow(false);
			this.opnvToolWindow.hideWindow(false);
		}
	});
	
	// Tooltip route length
	this.trackinfoToolWindow = new MMTrackinfoToolWindow();
	//this.tooltipRoutingProperties = new MMTooltip("Für Routenoptionen hier klicken");
	this.tooltipRoutingProperties = new MMTooltip('<table border="0"><tr><td><img src="'+ MMRegistry.urlPortal +'dateien/leftMouse.gif"></td><td>Route&nbsp;auswählen</td></tr><tr><td><img src="'+ MMRegistry.urlPortal +'dateien/rightMouse.gif"></td><td>Wegpunkte&nbsp;setzen/löschen</td></tr></table>');
	
	// Bike Menuicon
	this.bikeMenuIcon = new MMMenuIcon();
	this.bikeMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/bikeTour_disabled.gif");
	this.bikeMenuIcon.setTooltipText("Individuelle Einstellungen Routensuche");
	this.bikeMenuIcon.setSize(40,40);
	this.bikeMenuIcon.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,55)));	
	this.map.addControl(this.bikeMenuIcon);
	
	
	// Bahn/Bus Menuicon
	this.opnvMenuIcon = new MMMenuIcon();
	this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour_disabled.gif");
	this.opnvMenuIcon.setTooltipText('Transport des Fahrrads in Öffentlichen Verkehrsmitteln');
	this.opnvMenuIcon.setSize(40,40);
	this.opnvMenuIcon.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,100)));	
	this.map.addControl(this.opnvMenuIcon);	
	
	this.UpdateMenuIcons();
	
	// Tool Windows
	this.bikeToolWindow = new MMBikeToolWindow();
	this.bikeToolWindow.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(46,35)));
	this.map.addControl(this.bikeToolWindow);
	
	this.opnvToolWindow = new MMOpnvToolWindow();		
	this.opnvToolWindow.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(46,35)))
	this.map.addControl(this.opnvToolWindow);
	
	GEvent.bind(this.bikeToolWindow, "close", this, function(){
		
		if(this.selectedRoute)this.selectedRoute.SetSelection(false);
		this.selectedRoute = null;
		this.UpdateMenuIcons();
	});
	
	GEvent.bind(this.opnvToolWindow, "close", this, function(){
		if(this.selectedRoute)this.selectedRoute.SetSelection(false);
		this.selectedRoute = null;		
		this.UpdateMenuIcons();
	});
	
	
	GEvent.bind(this.bikeMenuIcon, "click", this, function(){
		
		if(!this.selectedRoute && this.routes.length == 1)
		{
			this.selectedRoute = this.routes[0];
			this.selectedRoute.SetSelection(true);
		}
		
		if(this.selectedRoute)
		{
			this.selectedRoute.SetOpnv(false);
			this.selectedRoute.load(false);
			this.bikeMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/bikeTour.gif");		
			this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour.gif");
			this.showTools(this.selectedRoute);
			this.opnvToolWindow.hideWindow(false);			
			this.bikeToolWindow.show(this.selectedRoute);			
		}
	});
	
	GEvent.bind(this.opnvMenuIcon, "click", this, function(){
		
		if(!this.selectedRoute && this.routes.length == 1 && this.routes[0].OpnvAvailable())
		{
			this.selectedRoute = this.routes[0];
			this.selectedRoute.SetSelection(true);
		}
		
		if(this.selectedRoute && this.selectedRoute.OpnvAvailable())
		{
			this.selectedRoute.SetOpnv(true);		
			this.selectedRoute.load(false);
			this.bikeMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/bikeTour.gif");		
			this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour.gif");
			this.showTools(this.selectedRoute);
			this.bikeToolWindow.hideWindow(false);			
			this.opnvToolWindow.show(this.selectedRoute);					
		}
	});
	
	
	
}

MMDirections.prototype.Clear = function()
{
	for(var i=0; i<this.waypoints.length; i++){
		this.map.removeOverlay(this.waypoints[i]);
	}	

	for(var i=0; i<this.routes.length; i++){
		this.map.removeOverlay(this.routes[i]);
	}

	this.waypoints = new Array();
	this.routes = new Array();
}

MMDirections.prototype.IsCostfree = function()
{
	for(var i=0; i<this.routes.length; i++){
		if(!this.routes[i].IsCostfree()) return false;
	}
	return true;
}

MMDirections.prototype.CountRoutes = function()
{
	return this.routes.length;	
}

MMDirections.prototype.CountWaypoints = function()
{
	return this.waypoints.length;	
}


MMDirections.prototype.AddStart = function(latLng)
{
	var waypoint = new MMWaypoint(latLng, 0);
	this.bindWaypointContextmenu(waypoint);
	this.map.addOverlay(waypoint);
	this.waypoints.unshift(waypoint);
	
	if(this.waypoints.length >= 2)
	{
		var from = this.waypoints[0];
		var to = this.waypoints[1];
		
		if(this.waypoints.length == 2) to.SetType(2);
		else if(this.waypoints.length >= 3) to.SetType(1);
					
		var route = new MMRoute(from, to);
		this.map.addOverlay(route);
		GEvent.bind(route, "click", this, this.ClickRoute);
		GEvent.bind(route, "mouseover", this, this.RouteMouseover);
		GEvent.bind(route, "mouseout", this, this.RouteMouseout);
		GEvent.bind(route, "mousemove", this, this.RouteMousemove);
		GEvent.bind(route, "routechanged", this, this.RouteChanged);		
		this.bindRouteContextmenu(route);
		this.routes.unshift(route);
		route.load();
		
		this.UpdateMenuIcons();
	}
	
}

MMDirections.prototype.AddEnd = function(latLng)
{
	var waypoint = new MMWaypoint(latLng, 2);
	this.bindWaypointContextmenu(waypoint);
	this.map.addOverlay(waypoint);
	this.waypoints.push(waypoint);
	
	if(this.waypoints.length >= 2)
	{		
		var from = this.waypoints[this.waypoints.length-2];
		var to = this.waypoints[this.waypoints.length-1];		
				
		if(this.waypoints.length == 2) from.SetType(0);
		else if(this.waypoints.length >= 3) from.SetType(1);
		
		var route = new MMRoute(from, to);
		this.map.addOverlay(route);
		GEvent.bind(route, "click", this, this.ClickRoute);
		GEvent.bind(route, "mouseover", this, this.RouteMouseover);
		GEvent.bind(route, "mouseout", this, this.RouteMouseout);
		GEvent.bind(route, "mousemove", this, this.RouteMousemove);
		GEvent.bind(route, "routechanged", this, this.RouteChanged);
		this.bindRouteContextmenu(route);
		this.routes.push(route);
		route.load();
		
		this.UpdateMenuIcons();		
	}
}

MMDirections.prototype.SplitRoute = function(route, point)
{
	var i = this.GetIndex(route);	

	// Add Via to Waypoints
	var viaWaypoint = new MMWaypoint(point, 1);
	this.bindWaypointContextmenu(viaWaypoint);
	this.map.addOverlay(viaWaypoint);
	
	var tmp = this.waypoints.slice(0, i+1);
	tmp.push(viaWaypoint);
	for(var n=i+1; n<this.waypoints.length; n++)tmp.push(this.waypoints[n]);	
	this.waypoints = tmp;	
	
	
	
	// Replace splitted route by 2 seperate routes
	var routeSplit1 = new MMRoute(route.GetStartWaypoint(), viaWaypoint);
	var routeSplit2 = new MMRoute(viaWaypoint, route.GetEndWaypoint());	
	
	routeSplit1.SetOpnv(route.GetOpnv());
	routeSplit1.SetTime(route.GetTime(), route.TimeIsDeparture());
	routeSplit1.SetTransportation(route.GetRegionalbahn(), route.GetSbahn(), route.GetUbahn(), route.GetBus());
	routeSplit1.SetSurface(route.GetSurface());
	routeSplit1.SetDifficulty(route.GetDifficulty());
	routeSplit1.SetDifficulty(route.GetDifficulty());
	
	routeSplit2.SetOpnv(route.GetOpnv());
	routeSplit2.SetTime(route.GetTime(), route.TimeIsDeparture());
	routeSplit2.SetTransportation(route.GetRegionalbahn(), route.GetSbahn(), route.GetUbahn(), route.GetBus());
	routeSplit2.SetSurface(route.GetSurface());
	routeSplit2.SetDifficulty(route.GetDifficulty());
	routeSplit2.SetDifficulty(route.GetDifficulty());
	
	this.map.addOverlay(routeSplit1);
	this.map.addOverlay(routeSplit2);
	
	GEvent.bind(routeSplit1, "click", this, this.ClickRoute);	
	GEvent.bind(routeSplit1, "mouseover", this, this.RouteMouseover);
	GEvent.bind(routeSplit1, "mouseout", this, this.RouteMouseout);
	GEvent.bind(routeSplit1, "mousemove", this, this.RouteMousemove);
	GEvent.bind(routeSplit1, "routechanged", this, this.RouteChanged);
	
	GEvent.bind(routeSplit2, "click", this, this.ClickRoute);
	GEvent.bind(routeSplit2, "mouseover", this, this.RouteMouseover);	
	GEvent.bind(routeSplit2, "mouseout", this, this.RouteMouseout);	
	GEvent.bind(routeSplit2, "mousemove", this, this.RouteMousemove);
	GEvent.bind(routeSplit2, "routechanged", this, this.RouteChanged);
	
	this.bindRouteContextmenu(routeSplit1);
	this.bindRouteContextmenu(routeSplit2);

	var tmp = this.routes.slice(0, i);	
	tmp.push(routeSplit1);	
	tmp.push(routeSplit2);	
	for(var n=i+1; n<this.routes.length; n++)tmp.push(this.routes[n]);
	this.routes = tmp;
	
	
	// Redraw
	this.map.removeOverlay(route);
	routeSplit1.load();
	routeSplit2.load();
	
	this.UpdateMenuIcons();
}

MMDirections.prototype.GetHeightdifferenceUp = function()
{
	var up = 0;
	for(var i=0; i<this.routes.length; i++)
	{
		up += this.routes[i].GetHeightdifferenceUp();
	}
	return up;
}

MMDirections.prototype.GetHeightdifferenceDown = function()
{
	var down = 0;
	for(var i=0; i<this.routes.length; i++)
	{
		down += this.routes[i].GetHeightdifferenceDown();
	}
	return down;
}


MMDirections.prototype.GetWaypointIndex = function(waypoint)
{
	for(var i=0; i<this.waypoints.length; i++)
	{
		if(this.waypoints[i] == waypoint) return i;
	}
	return false;
}

MMDirections.prototype.GetIndex = function(route)
{
	return this.routes.indexOf(route);
}

MMDirections.prototype.GetRoute = function(index)
{
	return this.routes[index];
}


MMDirections.prototype.bindWaypointContextmenu = function(waypoint)
{
	this.contextMenu = new MMContextmenu(waypoint, "rightclick");
	this.contextMenu.addItem("Wegpunkt entfernen", this, function(point){	
				
		for(var i=0; i<this.routes.length; i++)
		{
			if(this.routes[i].GetStartWaypoint() == waypoint)     var routeEnd = this.routes[i];
			else if(this.routes[i].GetEndWaypoint() == waypoint)  var routeStart = this.routes[i];
		}
		
		// merge route, if waypoint is not end or start
		if(routeStart && routeEnd){
			var mergedRoute = new MMRoute(routeStart.GetStartWaypoint(), routeEnd.GetEndWaypoint());
			this.map.addOverlay(mergedRoute);
			GEvent.bind(mergedRoute, "click", this, this.ClickRoute);
			GEvent.bind(mergedRoute, "mouseover", this, this.RouteMouseover);
			GEvent.bind(mergedRoute, "mouseout", this, this.RouteMouseout);
			GEvent.bind(mergedRoute, "mousemove", this, this.RouteMousemove);
			GEvent.bind(mergedRoute, "routechanged", this, this.RouteChanged);
			this.bindRouteContextmenu(mergedRoute);
			this.routes.push(mergedRoute);
			mergedRoute.load();
		}
		
		// remove waypoint
		this.map.removeOverlay(waypoint);		
		this.waypoints = this.removeItem(this.waypoints, waypoint);		
		
		// remove old routes
		if(routeStart)
		{
			this.map.removeOverlay(routeStart);
			this.routes = this.removeItem(this.routes, routeStart);
			
			if(this.waypoints.length > 1)this.waypoints[this.waypoints.length-1].SetType(2);
		}
		
		if(routeEnd)
		{
			this.map.removeOverlay(routeEnd);			
			this.routes = this.removeItem(this.routes, routeEnd);
			this.waypoints[0].SetType(0);
		}
		
		GEvent.trigger(this, "routechanged");
		
		this.UpdateMenuIcons();
	});
	
	this.contextMenu.addSeparator();
  	
  	this.contextMenu.addItem("Vergr&ouml;&szlig;ern", this, function(point){
		this.map.setCenter(point, this.map.getZoom()+1);
  	});
  	
  	this.contextMenu.addItem("Verkleinern", this, function(point){
		this.map.zoomOut();
  	});
  	
  	this.contextMenu.addItem("Karte hier zentrieren", this, function(point){
		this.map.panTo(point);
  	});
  	
  	this.map.addControl(this.contextMenu);
}


MMDirections.prototype.bindRouteContextmenu = function(route)
{
	this.contextMenu = new MMContextmenu(route, "rightclick");
	this.contextMenu.addItem("Wegpunkt hier einf&uuml;gen", this, function(point, route){
		this.SplitRoute(route, point);
	});
	
	this.contextMenu.addSeparator();
  	
  	this.contextMenu.addItem("Vergr&ouml;&szlig;ern", this, function(point){
		this.map.setCenter(point, this.map.getZoom()+1);
  	});
  	
  	this.contextMenu.addItem("Verkleinern", this, function(point){
		this.map.zoomOut();
  	});
  	
  	this.contextMenu.addItem("Karte hier zentrieren", this, function(point){
		this.map.panTo(point);
  	});
  	
  	this.map.addControl(this.contextMenu);
}


MMDirections.prototype.removeItem = function(array, item)
{
	var i = array.indexOf(item);
	var tmp = array.slice(0, i);
	for(var n=i+1; n<array.length; n++)tmp.push(array[n]);
	return tmp;	
}


MMDirections.prototype.ClickRoute = function(route, point){
	
	//this.UpdateMenuIcons()
	
	
	if(this.selectedRoute)this.selectedRoute.SetSelection(false);
	this.selectedRoute = route;
	this.selectedRoute.SetSelection(true);
	
	this.showTools(route);
	/*
	if(route.GetOpnv()){
		this.opnvToolWindow.show(this.selectedRoute);
	
	}else {
		this.bikeToolWindow.show(this.selectedRoute);	
	}
	*/

}

MMDirections.prototype.RouteMouseover = function(route, pxPoint){
	route.SetWeight(10);	
	
	this.map.addControl(this.tooltipRoutingProperties);
	this.tooltipRoutingProperties.show(pxPoint);
	
	this.map.addControl(this.trackinfoToolWindow);
	this.trackinfoToolWindow.show(route);
	
	if(!this.selectedRoute) this.showTools(route);
	
}

MMDirections.prototype.RouteMouseout = function(route){
	route.SetWeight(5);
	this.map.removeControl(this.trackinfoToolWindow);
	this.map.removeControl(this.tooltipRoutingProperties);
	this.UpdateMenuIcons();	
}

MMDirections.prototype.RouteMousemove = function(route, pxPoint){
	this.tooltipRoutingProperties.show(pxPoint);
}

MMDirections.prototype.RouteChanged = function(route){
	GEvent.trigger(this, "routechanged", route);
}


MMDirections.prototype.UpdateMenuIcons = function(){
	if(!this.selectedRoute)
	{
		//this.bikeMenuIcon.hide();
		//this.opnvMenuIcon.hide();
				
		this.bikeMenuIcon.setTooltipText('Individuelle Einstellungen Routensuche\n(Keine Route ausgewählt)');
		this.opnvMenuIcon.setTooltipText('Transport des Fahrrads in Öffentlichen Verkehrsmitteln\n(Keine Route ausgewählt)');
		
		if(this.routes.length == 1)
		{
			this.bikeMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/bikeTour.gif");
			
			if(this.routes[0].OpnvAvailable())this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour.gif");
			else this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour_disabled.gif");;
		}
		else
		{
			this.bikeMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/bikeTour_disabled.gif");
			this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour_disabled.gif");
		}
		
		this.bikeMenuIcon.show();
		this.opnvMenuIcon.show();
	}
}

MMDirections.prototype.showTools = function(route){
	
	this.bikeMenuIcon.setTooltipText('Individuelle Einstellungen Routensuche');
	this.opnvMenuIcon.setTooltipText('Transport des Fahrrads in Öffentlichen Verkehrsmitteln');

	this.bikeMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/bikeTour.gif");
	
	if(route.OpnvAvailable()){
		this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour.gif");
	}else {
		this.opnvMenuIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/opnvTour_disabled.gif");
	}
	
	this.bikeMenuIcon.show();
	this.opnvMenuIcon.show();

}

MMDirections.prototype.zoomToRoute = function(route)
{	
	var bounds = route.getBounds();
	
	var center = bounds.getCenter();
	var zoom = this.map.getBoundsZoomLevel(bounds);
	this.map.setCenter(center, zoom);
	this.map.savePosition();
}


MMDirections.prototype.zoomToDirections = function()
{
	var bounds = this.getBounds();
	
	var center = bounds.getCenter();
	var zoom = this.map.getBoundsZoomLevel(bounds);
	this.map.setCenter(center, zoom);
	this.map.savePosition();
}


/**
 * Returns the bounds for all Routes
 */
MMDirections.prototype.getBounds = function()
{
	var north;
	var east;
	var south;
	var west;
	
	for(vari=0; i< this.routes.length; i++)
	{
		var bounds = this.routes[i].getBounds();
		var southwest = bounds.getSouthWest();
		var northeast = bounds.getNorthEast();
		
		
		if(!north || northeast.lat() > north) north = northeast.lat();
		if(!east || northeast.lng() > east) east = northeast.lng();
		if(!south || southwest.lat() < south) south = southwest.lat();
		if(!west || southwest.lng() < west) west = southwest.lng();
	}
	
	if(north && east && south && west) return new GLatLngBounds(new GLatLng(south, west), new GLatLng(north, east));
	else return new GLatLngBounds();
}
