function GPolylineContainer(gPolyline){
  var gPolyline = gPolyline;
  var visible = false;
  var routeId = null;

  this.setVisible = function(visibility) {
    visible = visibility;
  }

  this.setRouteid = function (id) {
    routeId = id;
  }

  this.isVisible = function() {
    return visible;
  }

  this.getRouteid = function() {
    return routeId;
  }

  this.getGPolyline = function(){
    return gPolyline;
  }


}

function RouteController(map) {
  var routes = new Array();
  var currentRoute = null;
  var map = map;
  var polylineEncoder = new PolylineEncoder();
  var dbLoadedRoutes = new Array();// array of GPolyline
  var initialRequest = true;

  var checkAndCreateCurrentRoute = function(){
    if(currentRoute == null) {
      currentRoute = new Route(map,polylineEncoder);
      routes.push(currentRoute);
    }
  }

  var containsAnyOfGPolyline = function (gPolyline) {
    var mapBounds = map.getBounds();
    for(var i = 0 ; i < gPolyline.getVertexCount(); i++){
      if(mapBounds.containsLatLng(gPolyline.getVertex(i))){
        return true;
      }
    }
    return false;
  }

  var prepareParameters = function () {
     var bounds = map.getBounds();
    var sw = bounds.getSouthWest();
    var ne = bounds.getNorthEast();
    var retval =  {sw_lat:sw.lat(),sw_lng:sw.lng(),ne_lat:ne.lat(),ne_lng:ne.lng(), initialRequest: initialRequest};
    initialRequest &= false;
    return retval;
  }

  var isEditing = function() {
    return currentRoute != null;
  }

  var processServerResponse = function(routes) {
	  routes.each(function(route) {
	    Debug.log(route);
	    createAndAddGPolylineFromRoute(route);
	    Debug.log("finished creation");
	  });
	}

  var addGPolyline = function(gPolylineContainer) {
    var gPolyline = gPolylineContainer.getGPolyline();
    map.addOverlay(gPolyline);
    routeIcon.addStart(gPolyline.getVertex(0));
    routeIcon.addEnd(gPolyline.getVertex(gPolyline.getVertexCount()-1));
  }

  var createAndAddGPolylineFromRoute = function(route){
    if(! dbLoadedRoutes[route.id] ) {
      var gPolylineContainer = new GPolylineContainer( polylineEncoder.createGPolyline(route.encodedpoints, route.encodedlevels));
      gPolylineContainer.setVisible( true );
      gPolylineContainer.setRouteid ( route.id );
      dbLoadedRoutes[route.id] = gPolylineContainer;
      addGPolyline(gPolylineContainer);
    }
  }

  var placeGPolylineOnMap = function (gPolylineContainer) {
     if(gPolylineContainer) {
       var gPolyline = gPolylineContainer.getGPolyline();
       var isVisible = gPolylineContainer.isVisible();
	     if(isVisible && !containsAnyOfGPolyline(gPolyline)){
	       gPolylineContainer.setVisible( false );
	       map.removeOverlay(gPolyline);
	     }
	     else {
	       if(! isVisible){
	         gPolylineContainer.setVisible( true );
	         map.addOverlay(gPolyline);
	       }
	     }
     }
  }

  var showSingleRoute = function(routeId){
    Debug.log("showing route");
    var gPolylineContainer = dbLoadedRoutes[routeId];
    var gPolyline = gPolylineContainer.getGPolyline();
    map.panTo(gPolyline.getVertex(0));
  }

  var loadSingleRoute = function(id) {
     new Ajax.Request(loadSingleRouteUrl,
      {asynchronous:true,
        evalScripts:true,
        onSuccess:function(request, json){processServerResponse(json);showSingleRoute(id) },
        parameters: {id:id}});
   }

  this.activateRoute = function(routeId){
    if(! dbLoadedRoutes[routeId]) {
      loadSingleRoute (routeId);
      return;
    }
    showSingleRoute(routeId);
  }

  this.captureMoveStartEvent = function() {
  }

  this.loadAllInBound = function() {
    new Ajax.Request(loadAllInBoundUrl,
     {asynchronous:true,
       evalScripts:true,
       onSuccess:function(request, json){processServerResponse(json)},
       parameters: prepareParameters()});
  }


  this.captureMoveEndEvent = function() {
    Debug.log('moveend');
    // deactivated when editing
    if(! isEditing()) {
	    routeController.loadAllInBound();
	    dbLoadedRoutes.each(function(gPolyline){
        placeGPolylineOnMap(gPolyline);
	    });
    }
  }


  this.persistPolylineAndClearInput = function () {
    var gPolylineContainer = new GPolylineContainer(polylineEncoder.dpEncodeToGPolyline(currentRoute.getRoutePoints()) );
    this.clearAll();
    addGPolyline(gPolylineContainer);
  }

  this.getCurrentRoute = function () {
    checkAndCreateCurrentRoute();
    return currentRoute;
  }

  this.mapClick = function (overlay, point) {
    checkAndCreateCurrentRoute();
    if(!overlay) {
      currentRoute.addRoutePoint(point);
    }
  }

  this.clearAll = function () {
    for(var i = 0 ; i < routes.length ; i++) {
      routes[i].resetRoute();
    }
    currentRoute = null;
  }

  this.addClosing = function() {
    currentRoute.addClosing();
    currentRoute = null;
    Debug.log("closing");
  }

  this.undoPoint = function() {
    if( ! currentRoute && routes.length > 0  ) {
      currentRoute = routes.pop();
    }
    if(! currentRoute ) {
      return;
    }

    currentRoute.undoPoint();

    if(currentRoute.getRoutePoints().length == 0) {
      currentRoute = null;
      Debug.log("currentRoute should be cleared !! ");
      Debug.log("currentRoute " +  currentRoute);
    }
  }

  this.printRoutes = function () {
    for(var i = 0 ; i < routes.length ; i++) {
      Debug.log("Route " + (i + 1) + " : " );
      var routePoints = routes[i].getRoutePoints();
      var prevPoint = null;
      var overallDist = 0;
      for (var n = 0 ; n < routePoints.length ; n++ ) {

        var dist = 0;
        if (prevPoint) {
          dist = prevPoint.distanceFrom(routePoints[n]).toFixed(0) / 1000;
        }

        Debug.log(routePoints[n].lng().toFixed(8) + ', ' + routePoints[n].lat().toFixed(8) + ', ' + dist );
        prevPoint = routePoints[n];
        overallDist += dist;
      }
      Debug.log("Overall distance: " + overallDist );
      Debug.log('----- new line ------ \n');
    }
  }
}

