//*     cProfil() - jurk@webit.de

    //*     usage:
    //*     "altitudes" ist der komplette Array (Indexposition entspricht der Position der Vertexpunkte in der Polyline)
    //*     mit den Höhen in Meter

    //*     dom: htmlelement welches das Profil enthalten soll

    //*     oPolyline:GPolyline
    //*     oMap:GMap
    //*     oIcon:GIcon
    
    //~ var profil = new cProfil(oMap,oPolyline,oIcon)
      
    //~ profil.draw({dom:'profil',width:800,height:100,cursorWidth:1,linecolor:'ff0000',linewidth:1,chartbackground:'cae073',background:'f8fDDD'});
    
    //~ profil.redraw('profil',{width:200,height:100});
    
    //~ profil.remove('profil');



function cProfil(oMap,oPolyline,oIcon)  {

  if(!oMap || !oPolyline || !oIcon) {throw("new cProfil(oMap,oPolyline,oIcon) - Attribute nicht vollständig.");}
  
  if(!oPolyline.__altitudes) {throw("new cProfil(oMap,oPolyline,oIcon) - oPolyline enthält keine Höhendaten (oPolyline.__altitudes).");}

  
  this._oMap = oMap;
  this._oIcon = oIcon;
  this._oPolyline = oPolyline;
  this._altitudes = oPolyline.__altitudes;

  
  
  this._charts = {}; //* Objekt enthält alle charts
  this._interval = null; //* Interval wird gesetzt um die Karte an den richtigen Punkt zu schieben
  
  this.vCount = this._oPolyline.getVertexCount();
  this.aCount = this._altitudes.length;
  this.length = this._oPolyline.getLength();
  
  
  this.curAltitude = null;
  this.curPos = null;
  
  this.oNorthpole = new google.maps.LatLng(0,90);
  this.oMarker = new google.maps.Marker(this.oNorthpole,{icon:this._oIcon});  
  this.oGoogleChart = new cGoogleChart(this._altitudes,this.length);
  this.oSnap = new cSnapToRoute(this._oMap, this.oMarker,this._oPolyline);
  
  
  this._oMap.addOverlay(this.oMarker);
  
  //~ 
   
  this.redraw = function(dom,options){
    this.remove(dom);
    //* neue optionen setzen, alte beibehalten.
    for(var o in options || {}){ this._charts[dom].options[o] = options[o]; }
    //* neumalen
    this.draw(this._charts[dom].options);
  };
  
  this.remove = function(dom){
    if(!this._charts[dom]){ throw("Angebendes DOM Element ("+dom+") enthält kein Profil."); }
    //* Events entfernen
    for(var e in this._charts[dom].events){ google.maps.Event.removeListener(this._charts[dom].events[e]); }
    this._charts[dom].events = null;
    //* ausblenden
    if(document.getElementById(dom)){ document.getElementById(dom).style.display ="none"; }
  };

  //~
  //* draw() dar nur einmal auf dem angegebenen DOM Objekt angewand werden / 
  //* redraw() für das neumalen des Profils verwenden.
  
  this.draw = function(options) {
    
    //~ google.maps.Log.write("Vertexcount: "+this.vCount+" Altitudescount: "+this.aCount);
    
    var profil = document.getElementById(options.dom);
    if(!profil) { throw("cProfil(oMap,oPolyline,oIcon,altitudes) - DOM element '"+options.dom+"' wurde nicht gefunden"); }
    
    if(this._charts[options.dom] && this._charts[options.dom].events){ this.remove(options.dom); } // * events sind noch vorhanden und müssen entfernt werden
    
    this._charts[options.dom] = {options:options,events:[]};
    
    
    //* style nehmen wenn schon da und keine andere größe angegeben
    var width = options.width || this.getStyle(profil,'width') || 800;
    var height = options.height || this.getStyle(profil,'height') || 100;
    
    var cursorWidth = options.cursorWidth || 2;

    var background = options.background || "f8fDDD";
    var linecolor = options.linecolor || 'ff0000';
    var linewidth = options.linewidth || 2;
    var chartbackground = options.chartbackground || "cae073";
    
    
    var chart_image = this.oGoogleChart.generate({width:width,height:height,background:background,linecolor:linecolor,linewidth:linewidth,chartbackground:chartbackground});
    
    //* Rand im Chartbild bis zu den eigentlichen Daten muss ggf angepasst werden
    var margin = {top:10,left:32,bottom:18,right:10};

    
    //* Chartbild und Coursor setzen
    var profil_style =  {width:width+'px',height:height+'px',backgroundImage:"url("+chart_image+")",position:'relative',overflow:'hidden',cursor:'pointer',display:''};
    for(var k in profil_style){ profil.style[k] = profil_style[k]; }
    var line = document.createElement('div');
    var line_style =  {width:cursorWidth+'px',height:height-margin.top-margin.bottom+'px',top:margin.top+'px',background:'red',position:'absolute',overflow:'hidden'};
    for(var k in line_style){ line.style[k] = line_style[k]; }
    
    var self = this;


    //* Events auf der Karte / Polyline
    var md;
    var miu = true; // mouse is up
    var mio = true; // mouse is out

    var polyline_event = google.maps.Event.addListener(this._oPolyline, "mouseover", function(){
      mio = false;
      self._oMap.disableDragging();
      var md = google.maps.Event.addListener(self._oMap.getDragObject(), "mousedown", function(){
	miu = false;
        self.oSnap.startInterval();
	self.oSnap.updateMarkerLocation(self.oNorthpole);
        var mm = google.maps.Event.addListener(self._oMap, 'mousemove', function(point) {
          self.oSnap.updateMarkerLocation(point);
          if (self.oSnap.curIndex){
            line.style.left = parseInt((self.oSnap.curIndex*(width-margin.left-margin.right)/self.vCount)+margin.left-cursorWidth).toString()+'px';
            profil.appendChild(line);
            self.setInfo(self.oSnap.curIndex);
          }
        });
        
        var mu = google.maps.Event.addListener(self._oMap.getDragObject(), "mouseup", function(){
	  miu = true;
          self.oMarker.setPoint(self.oNorthpole);
          self.oSnap.stopInterval();
          if (mio) self._oMap.enableDragging();
          google.maps.Event.removeListener(mm);
          google.maps.Event.removeListener(mu);
          if(line.parentNode == profil){ profil.removeChild(line); }
          self.curAltitude = self.curPos = null;
        });
        
//        google.maps.Event.removeListener(md);
      });
    });
   
    var mo = google.maps.Event.addListener(this._oPolyline, "mouseout", function(){
	google.maps.Event.removeListener(md);
	mio = true;
	if (miu) self._oMap.enableDragging();
    }); 

    //* Events im Profil
    var dom_event1 = google.maps.Event.addDomListener(profil, 'selectstart',function(){return false;} ); // im IE selection verhindern
    var dom_event2 = google.maps.Event.addDomListener(profil, 'mousedown',function(e){
      if(e.stopPropagation){ e.stopPropagation(); } // im draggen im FF verhindern
      var offsetX = (e.pageX ? e.pageX - self.getPos(this)[0] : window.event.clientX+document.body.scrollLeft-self.getPos(this)[0]-2);
      var p = (offsetX-margin.left)*100/(width-margin.left-margin.right);
      self.updateMarkerLocation(p);
      //* Interval setzen das die Karte an die richtige Position schiebt
      self.setMapPosition();
      profil.style.cursor = 'e-resize';
      line.style.left = (offsetX-cursorWidth).toString()+'px';
      profil.appendChild(line);
      var mm =  google.maps.Event.addDomListener(profil, 'mousemove',function(e){
        if(e.preventDefault){ e.preventDefault(); }
        var position = self.getPos(this);
        var offsetX = (e.pageX ? e.pageX - position[0] : window.event.clientX+document.body.scrollLeft-position[0]-2);
        var offsetY= (e.pageY ? e.pageY - position[1] : window.event.clientY+document.body.scrollTop-position[1]-2);
        var p = (offsetX-margin.left)*100/(width-margin.left-margin.right);
        line.style.left = (offsetX-cursorWidth).toString()+'px';
        self.updateMarkerLocation(p);
        if (offsetX < margin.left || offsetX > width - margin.right || offsetY < 2 || offsetY  > height - 2) {
          profil.style.cursor = 'pointer';
          if(line.parentNode == profil){ profil.removeChild(line); }
          self.oMarker.setPoint(self.oNorthpole);
          self.curAltitude = self.curPos = null;
          google.maps.Event.removeListener(mm);
          //* Interval löschen das die Karte an die richtige Position schiebt
          window.clearInterval(self._interval);
        }
      });
      var mu = google.maps.Event.addDomListener(profil, 'mouseup',function(){
        profil.style.cursor = 'pointer';
        if(line.parentNode == profil){ profil.removeChild(line); }
        self.oMarker.setPoint(self.oNorthpole);
        self.curAltitude = self.curPos = null;
        google.maps.Event.removeListener(mm);
        google.maps.Event.removeListener(mu);
        //* Interval löschen das die Karte an die richtige Position schiebt
        window.clearInterval(self._interval);
      });
    });
    
    //* Events archivieren um sie später entfernen zu können
    this._charts[options.dom].events.push(dom_event1,dom_event2,polyline_event);
    
  };
  
  this.updateMarkerLocation = function(p) {
    p = p > 100 ? 100 : p;
    p = p < 0 ? 0 : p;
    var aIndex = Math.round((this.aCount-1)*p/100);
    var vIndex = Math.round((this.vCount-1)*p/100);
    this.setInfo(aIndex,vIndex);
    this._curPoint = this._oPolyline.getVertex(vIndex);
    this.oMarker.setLatLng(this._curPoint);
  };
  
  this.setInfo = function(aIndex,vIndex) {
    this.curAltitude = this._altitudes[aIndex]; // Höhe in Meter
    this.curPos = vIndex * this.length / this.vCount; // Abstand vom ersten Punkt in Meter
  };
  
  //* Interne Funktion um die absolute Position eines DOM Elements zu bestimmen.
  this.getPos = function(obj) {
    var curleft = 0; var curtop = 0;
    if (obj.offsetParent) {while (obj.offsetParent) { curleft += obj.offsetLeft; curtop += obj.offsetTop; obj = obj.offsetParent; } } else if (obj.x && obj.y) {curleft = obj.x; curtop = obj.y;}
    return [curleft,curtop];
  };
  
  this.getPos_alt = function(obj) {
    var curleft = 0;
    var curtop = 0;
    var border;
    var padding;
    if (obj.offsetParent) {
      do {
        if (this.getStyle(obj, 'position') != 'absolute') {
          if (border = this.getStyle(obj, 'border-top-width')) curtop += parseInt(border);
          if (border = this.getStyle(obj, 'border-left-width')) curleft += parseInt(border);

          if (padding = this.getStyle(obj, 'padding-top')) curtop += parseInt(padding);
          if (padding = this.getStyle(obj, 'padding-left')) curleft += parseInt(padding);
        }
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while (obj = obj.offsetParent)
    } else if (obj.x) {
      curleft += obj.x;
      curtop += obj.y;
    }
    return [curleft,curtop];
  };
  
  //* Interne Funktion um übergebene Styleeigenschaften eines DOM Elements zu ermitteln.
  this.getStyle = function (x,styleProp) {
    var y = x.style[styleProp];
    if(!y) {
      if (x.currentStyle) {
        var y = x.currentStyle[styleProp];
      } else if (window.getComputedStyle) {
        var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
      }
    }
    y = (styleProp == 'width' && y == 'auto') ?  x.offsetWidth : y
    y = (styleProp == 'height' && y == 'auto') ?  x.offsetHeight : y
    return y;
  };
  
  this.setMapPosition = function() {
    var self = this;
    window.clearInterval(self._interval);
    self._interval = window.setInterval(function() {
      if(self._curPoint){ self._oMap.panTo(self._curPoint); }
    },500);
  };

}

