//*     cSnapToRoute() - jurk@webit.de
//*     cGoogleChart() - jurk@webit.de

    //* Hilfsklassen für cProfil könnten später mit in die profil.js

    //* usage:

    //~ var oSnapToRoute = new cSnapToRoute(oMap, oMarker, oPolyline)


    //*     maus ist auf der polyline

    //~ oSnapToRoute.startInterval()


    //~     maus bewegt sich auf der polyline

    //* oSnapToRoute.updateMarkerLocation(point)


    //*     verlassen der polyline

    //~ oSnapToRoute.stopInterval()

function cSnapToRoute(oMap, oMarker, oPolyline){
  this.vertex = Array();
  this.debug = 0;
  this.intervalTime = 80; //ms
  this.interval; // Interval referenz
  this.curIndex;
  
  this._oMap = oMap;
  this._oMarker = oMarker;
  this._oPolyline = oPolyline;
  
  this.vertexCount = this._oPolyline.getVertexCount();
  this.oMapBound = this._oMap.getBounds();
  this.oPolylineBound = this._oPolyline.getBounds()
  this.oProj = this._oMap.getCurrentMapType().getProjection();
  
  this.oMouseLatLng = new google.maps.LatLng(0,90)
  
  //~ Marker neu setzen und den Vertexindex@Markerposition zurückgeben
  this.updateMarkerLocation = function(mouseLatLng){
    this.oMouseLatLng  = mouseLatLng;
  }
  
  // hier wird die eigentliche Rechnung angeschubst
  this.startInterval = function(){
    var self = this;
    
    clearInterval(self.interval)
    self.interval = setInterval(function() {
      self.getVertexIndex()
      if(self.curIndex) self._oMarker.setPoint(self._oPolyline.getVertex(self.curIndex));
    },self.intervalTime);
    
  }
  
  this.stopInterval = function(){
    clearInterval(this.interval)
  }

  
  //~ bei verschieben / zoomen vertexpunkte neu laden
  this.loadMapListener = function(){
    var self = this;
    google.maps.Event.addListener(self._oMap, 'zoomend', google.maps.Event.callback(self, self.loadVertexPoints));
    google.maps.Event.addListener(self._oMap, 'moveend', google.maps.Event.callback(self, self.loadVertexPoints));
  }
  
  
  //~ Punke anhand des Auflösungsfaktors reduzieren und ggf Ausschnitt berechnen
  this.loadVertexPoints = function() {
    clearInterval(this.interval);
    this.oMapBound = this._oMap.getBounds();
    //~ range gesetzt anhand von schätzungen
    var resolution = parseInt(this.vertexCount / 300 +1) // Grundauflösung
    this.vertex = [] // leermachen
    
    if (this.oMapBound.containsBounds(this.oPolylineBound)){
      // alle Punkte hinzufügen (erste und letzter)
      this.vertex.push(0)
      this.vertex.push(this.vertexCount)
      
    } else if(this.oPolylineBound.intersects(this.oMapBound)){
    
      for( var i=0; i < this.vertexCount; i+=resolution ) {
        if(this.oMapBound.containsLatLng(this._oPolyline.getVertex(i))) this.vertex.push(i); // BoundingBox der Karte enthält Punkt
      }
      
    }
  }
  
  this.getVertexIndex = function() {
    //~ BoundingBox um Punkt aufbauen (20x20 Pixel)
    var point_xy = this.oProj.fromLatLngToPixel(this.oMouseLatLng,this._oMap.getZoom());
    var bound = new google.maps.LatLngBounds(
      this.oProj.fromPixelToLatLng(new google.maps.Point(point_xy.x-10,point_xy.y+10),this._oMap.getZoom()),
      this.oProj.fromPixelToLatLng(new google.maps.Point(point_xy.x+10,point_xy.y-10),this._oMap.getZoom())
    );
    // range ensprechend der zoomstufen wird eine auflösung gewählt
    var range = {"18":1,"17":1,"16":1,"15":1,"14":1,"13":2,"12":2,"11":3,"10":4,"9":5,"8":6,"7":7,"6":8,"5":9,"4":10,"3":11,"2":12,"1":13};
    var resolution = range[this._oMap.getZoom()] 
    var indexes = [];
    for( var i=Math.max(0,this.vertex[0]-10); i < Math.min(this.vertexCount,this.vertex[this.vertex.length-1]+10); i+=resolution) {
      //~ this.debug++;q
      if(bound.containsLatLng(this._oPolyline.getVertex(i))) indexes.push(i); // BoundingBox enthält Punkt
    }

    //~ google.maps.Log.write("Vertexcount: "+this.vertexCount+" Loops: "+this.debug+ " Vertexes: "+indexes.length+" Inputdata: "+this.vertex.length)
    //~ this.debug = 0;
    this.curIndex = indexes.length > 0 ? indexes[0] : null;
  }
  
  this.loadMapListener();
  this.loadVertexPoints();

}


//~ length in meter
//~ data ist der komplette array mit den höhen in meter

//~ die x Achse wird immer in Kilometer (min 5 km Schritte) die y Achse in Meter (min 50 m Schritte)

//~     usage
//~ var oGoogleChart = new cGoogleChart(altitudes,length)
//~ var chart_image = oGoogleChart.generate({width:400,height:100,linecolor:'ff0000',linewidth:1,chartbackground:'ffffff',background:'00ff00'})

function cGoogleChart(data,length) {

  if(!(data instanceof Array) || !length) {throw("cGoogleChart(data,length) - Attribute nicht vollständig.")}

  this._data = data || [];
  this._length = length || 100;
  this._count = this._data.length;
  this._options = {}
  
  this.generate = function(options){
  
    this._options = options || this._options
    
    var background = this._options.background || "f8fDDD";
    var linecolor = this._options.linecolor || 'ff0000';
    var linewidth = this._options.linewidth || 2;
    var chartbackground = this._options.chartbackground || "cae073";
    
    var width = this._options.width || 800;
    var height = this._options.height || 100;
    var points = [];
    
    var resolution = parseInt(this._count/(width*0.25)) || 1; // Punktauflösung: alle 4 Pixel ein Datenpunkt
    var min = 8848;
    var max = -10000;
    
    for(var k = 0; k < this._count; k+=resolution) {
      points.push(data[k]);
      min = min > data[k] ? data[k] : min;
      max = max < data[k] ? data[k] : max;
    }
    //~ auf ganze zahlen runden
    max = Math.round(max/100+0.5)*100;
    min = Math.round(min/50-0.5)*50;
    var length = Math.round(this._length/10000+0.5)*10;
    
    var length_real = Math.round(this._length/100+0.5)/10;
  
    var _y = "|1:";
    
    //~ schrittgröße anhand der auflösung setzen 40 pixel platz schrittweite 5 km bzw 50 m
    var steps_x = Math.round(length/(width/40)/5+0.5)*5
    var steps_y = Math.round((max-min)/(height/40)/50+0.5)*50
    
    var laststep_x = length_real
    var laststep_y = max
    
    for(var k = min; k <= max-steps_y; k+=steps_y) { _y+="|"+k; laststep_y = k;}
    
    var _xgrid = 100/(length_real/steps_x)
    var _ygrid = 100/((laststep_y+steps_y-min)/steps_y)
    
    return "http://chart.apis.google.com/chart?cht=lc&chma=30,10,10,10&chls="+linewidth+",1,0&chxt=x,y&chxl=0:|0|km+"+_y+"|m&chxr=0,0,"+length_real+","+steps_x+"&chg="+_xgrid+","+_ygrid+",1,0&chco="+linecolor+"&chm=B,"+chartbackground+",0,0,0&chf=bg,s,"+background+"&chs="+width+"x"+height+"&chd=t:"+points.join(',')+"&chds="+min+","+max;
  }
  
}

