/* CLookStopDrawer.js */
if( typeof gCLOOKSTOPDRAWER == 'undefined' ){
  var gCLOOKSTOPDRAWER = 'defined';
  var gLookStopDrawerRegistry = new Array();
  var gLookStopDrawerReferenceCount = gLookStopDrawerReferenceCount?gLookStopDrawerReferenceCount:0;
  /**
   * @brief General class to show Stops
   *
   * - uses Canvas to draw stops
   * - needs own div containers at initialization
   **/
  var ALookStopDrawer = Class.create();
  ALookStopDrawer.prototype = {

    // public interface

    minstopradius : 2,
    maxstopradius : 4,
    stopradiusfaktor : 10,
    stopradius : 4,
    maxtextwidth:160,
    mousoversize:14,
    // constructor
    initialize: function() {
      this.referencecount = gLookStopDrawerReferenceCount;
      gLookStopDrawerRegistry[this.referencecount] = this;
      gLookStopDrawerReferenceCount++;
    },

    // initialization
    init: function( aStopDivContainer, aTextDivContainer, aDetailsDivContainer, aMouseDivContainer, aWidth, aHeight ) {
      this.width = aWidth;
      this.height = aHeight;
      this.initializeCanvasDiv(aStopDivContainer);
      this.initializeTextDiv(aTextDivContainer);
      this.initializeDetailsDiv(aDetailsDivContainer);
      this.initializeMouseDiv(aMouseDivContainer);
    },

    setMouseManager: function( aMouseManager ){
      this.mousemanager = aMouseManager;
    },
    setTransformer: function( aTransformer ){
      this.transformer = aTransformer;
    },

    getTransformer: function(){
      if( typeof this.transformer == 'undefined' ) alert('CLookStopDrawer::getTransformer(): No Transformer available');
      return this.transformer;
    },
    getStopRadius: function( numberofstops ){
      var area = this.width * this.height;
      return Math.round( Math.min( Math.max(
                Math.sqrt( area / numberofstops ) / this.stopradiusfaktor,
                this.minstopradius ),
                this.maxstopradius ) );
    },
    drawtextontextdiv:function(x,y,text,align){
      var elem = document.createElement( 'div' );
      elem.style.position = 'absolute';
      elem.style.fontSize = 'x-small';
      elem.style.top = Math.round(y - 6) + 'px';
      if( align == "right" )
        elem.style.right = Math.round(this.width - x + 8) + 'px';
      else
        elem.style.left = Math.round(x + 8) + 'px';
      elem.innerHTML = '<nobr>' + text + '</nobr>';
      this.textdiv.appendChild( elem );
    },
    drawstop: function (x,y,stop){
      if (this.stopcanvas.getContext){
        var ctx = this.stopcanvas.getContext('2d');
        ctx.save();
        ctx.translate(x+0.5,y+0.5);
        var colarray = help.getproductclasscolours( stop.prodclass );
        ctx.beginPath();
        ctx.fillStyle = "rgba(0,0,0,0.15)";
        ctx.arc(0,0,this.stopradius+colarray.length*1,0,Math.PI*2.0,true);
        ctx.fill();
        for( var p = 0, dia = colarray.length-1; p < colarray.length ; p++, dia-- ){
          ctx.beginPath();
          ctx.fillStyle = colarray[p];
          ctx.arc(0,0,this.stopradius+dia*1,0,Math.PI*2.0,true);
          ctx.fill();
        }
        ctx.beginPath();
        ctx.fillStyle = "rgba(255,255,255,1)";
        ctx.arc(0,0,this.stopradius-1,0,Math.PI*2.0,true);
        ctx.fill();
        if( stop.startstop && stop.startstop == "yes" ){
          ctx.beginPath();
          ctx.strokeStyle = "rgba(255,0,0,1)";
          ctx.moveTo(this.stopradius,0);
          ctx.lineTo(-this.stopradius,0);
          ctx.moveTo(0,this.stopradius);
          ctx.lineTo(0,-this.stopradius);
          ctx.stroke();
        }
        if( stop.termstop && stop.termstop == "yes" ){
          ctx.rotate(Math.PI*0.25);
          ctx.beginPath();
          ctx.strokeStyle = "rgba(255,0,0,1)";
          ctx.moveTo(this.stopradius,0);
          ctx.lineTo(-this.stopradius,0);
          ctx.moveTo(0,this.stopradius);
          ctx.lineTo(0,-this.stopradius);
          ctx.stroke();
        }
        ctx.restore();
      } else {
        alert( "Canvas Context not found" );
      }
    },
    drawpoi: function (x,y){
      if (this.stopcanvas.getContext){
        var ctx = this.stopcanvas.getContext('2d');
        ctx.save();
        ctx.translate(x,y);

        ctx.beginPath();
        ctx.fillStyle = "rgba(255,255,255,1)";
        ctx.arc(0,0,this.stopradius,0,Math.PI*2.0,true);
        ctx.fill();

        ctx.beginPath();
  	    ctx.strokeStyle = "rgba(0,0,255,1)";
        ctx.lineWidth = "1";
        ctx.arc(0,0,this.stopradius,0,Math.PI*2.0,true);
        ctx.stroke();

        ctx.restore();
      } else {
        alert( "Canvas Context not found" );
      }
    },
    interpretstopinfo: function( info ){
      var poiinfo = info;
      var poi = new Object();
      var nextpos = -1;
      var aktpos = 0;
      nextpos = poiinfo.search(/\|/);
      if( nextpos == -1 ){
        poi.name = poiinfo;
      }else{
        poi.name = poiinfo.slice(aktpos,nextpos);
        poiinfo = poiinfo.slice(nextpos+1);
        nextpos = poiinfo.search(/\|/);
        if( nextpos == -1 )
          poi.x = Math.round((poiinfo) * 1000000);
        else{
          poi.x = Math.round((poiinfo.slice(aktpos,nextpos)) * 1000000);
          poiinfo = poiinfo.slice(nextpos+1);
          nextpos = poiinfo.search(/\|/);
          if( nextpos == -1 )
            poi.y = Math.round((poiinfo) * 1000000);
          else{
            poi.y = Math.round((poiinfo.slice(aktpos,nextpos)) * 1000000);
            poiinfo = poiinfo.slice(nextpos+1);
            nextpos = poiinfo.search(/\|/);
            if( nextpos == -1 )
              poi.dist = poiinfo;
            else{
              poi.dist = poiinfo.slice(aktpos,nextpos);
              poiinfo = poiinfo.slice(nextpos+1);
              nextpos = poiinfo.search(/\|/);
              if( nextpos == -1 ){
                alert( poiinfo );
                poi.image = poiinfo;
              }else{
                poi.image = poiinfo.slice(aktpos,nextpos);
                poiinfo = poiinfo.slice(nextpos+1);
                poi.url = poiinfo;
              }
            }
          }
        }
      }
      if( poi.name ){
        nextpos = poi.name.search(/\,/);
        if( nextpos == -1 )
          poi.shortname = poi.name;
        else
          poi.shortname = poi.name.slice(0,nextpos);
      }
      return poi;
    },

    drawstopdetails: function(x,y,stop){
      var mx = Math.round(x);
      var my = Math.round(y);
      var name = '';
      var info = '';
      var poi = '';

      if( stop.name ) name = stop.name;

      if( stop.info ) {
        info = stop.info;
        poi = this.interpretstopinfo( info );
      }

      // mouseover for stop
      if( info == '' )
        this.drawmouseoverdiv( x, y, name, '' );
      else
        this.drawmouseoverdivstopwithpoi( x, y, name, poi );

      if( poi != '' ){
        // draw poi
        if( poi.x != '' && poi.y != '' ){
          var mpoix = this.getTransformer().getX( poi.x, poi.y );
          var mpoiy = this.getTransformer().getY( poi.x, poi.y );
          this.drawpoi( mpoix, mpoiy );
          this.drawtextontextdiv( mpoix, mpoiy, poi.shortname );
        }
        // mouseover for poi
        this.drawmouseoverdivpoi( mpoix, mpoiy, name, poi );
      }
    },

    drawmouseoverdivpoi: function( x, y, stopname, poi ){
      if( typeof gImagePath == 'undefined' ) alert( 'ALookStopDrawer::drawinfo: gImagePath not set' );
      var text = '';
      if( poi.image && poi.image != '' )
        text += '<img src=\''+gImagePath+'look/' + poi.image+'\' /><br>';
      if( stopname != '' )
        text += 'Take the stop '+stopname+'<br>';
      if( poi.dist != '' && poi.dist != '0' )
        text += 'Just '+poi.dist+'km to go.<br>';
      if( typeof poi.name != 'undefined' )
        this.drawmouseoverdiv( x, y, poi.name, text, poi.url );
    },

    drawmouseoverdivstopwithpoi: function( x, y, stopname, poi ){
      var text = '';
      if( poi.name != '' )
        text += 'Close by Attraction: '+poi.name+'<br>';
      if( poi.dist != '' && poi.dist != '0' )
        text += 'Just '+poi.dist+'km to go.';
      this.drawmouseoverdiv( x, y, stopname, text );
    },

    drawmouseoverdiv: function( x, y, name, text, url ){
      if( gLookStopDrawerRegistry[this.referencecount] != this ){ alert( 'drawmouseoverdiv(): global Registry failed' ); }
      var elem = document.createElement( 'div' );
      elem.style.position = 'absolute';
      elem.style.left = Math.round(x - this.mousoversize/2) + 'px';
      elem.style.top = Math.round(y - this.mousoversize/2) + 'px';
      elem.style.width = this.mousoversize + 'px';
      elem.style.height = this.mousoversize + 'px';
      elem.id = 'mouseoverdiv_'+this.referencecount;
      elem.onmouseover = this.showdetails.bind(this, Math.round(x), Math.round(y), name, text);
      elem.onmouseout = this.hidedetails.bind(this);
      if( url && url != '' ){
        elem.onclick = this.showexternalurl.bind( this, url, "Attraction" );
      }
      this.mousediv.appendChild( elem );
    },
    showexternalurl: function( url, name ){
      window.open( url, name );
    },
    showdetails: function(x,y,name,text){
      var leftpx = Math.round(x + 20);
      var tmptext = '<div class="look_info" style="' +
        'top:' + Math.round(y - 8) + 'px;' +
        'left:' + leftpx + 'px;' +
        'max-width:' + '226' + 'px;' +
        '">' +
          '<div class="look_info_title" style="' +
          '">' + name + '</div>';
      if( text && text != '' )
        tmptext +=
            '<div class="look_info_body" style="' +
            '">' + text + '</div>';
      tmptext += '</div>';
      this.detailsdiv.innerHTML = tmptext;
    },

    hidedetails: function(){
      this.detailsdiv.innerHTML = '';
    },

    clearAllDivs: function(){
      this.clearCanvasDiv();
      CNodes.removeAllChilds( this.textdiv );
      CNodes.removeAllChilds( this.detailsdiv );
      CNodes.removeAllChilds( this.mousediv );
    },
    initializeCanvasDiv: function( divcontainer ) {
      this.stopdiv = this.addDivElem( this.getElemName( 'StopDiv' ), divcontainer );
      this.stopcanvas = this.addCanvasElem(
            this.getElemName(this.stopdiv.id + 'canvas'),
            this.stopdiv );
      if (ie6&&!ie7&&this.stopcanvas.getContext){
        var ctx = this.stopcanvas.getContext('2d');
        ctx.fillStyle = "rgba(255,255,255,0.01)";
        ctx.fillRect(0,0,this.width,this.height);
      }
    },

    clearCanvasDiv: function() {
      CNodes.removeAllChilds( this.stopdiv );
      this.stopcanvas = this.addCanvasElem(
            this.getElemName(this.stopdiv.id + 'canvas'),
            this.stopdiv );
      if (ie6&&!ie7&&this.stopcanvas.getContext){
        var ctx = this.stopcanvas.getContext('2d');
        ctx.fillStyle = "rgba(255,255,255,0.01)";
        ctx.fillRect(0,0,this.width,this.height);
      }
    },

    initializeTextDiv: function( divcontainer ) {
      this.textdiv = this.addDivElem( this.getElemName( 'TextDiv' ), divcontainer );
    },

    initializeDetailsDiv: function( divcontainer ) {
      this.detailsdiv = this.addDivElem( this.getElemName( 'DetailsDiv' ), divcontainer );
    },

    initializeMouseDiv: function( divcontainer ) {
      this.mousediv = this.addDivElem( this.getElemName( 'MouseDiv' ), divcontainer );
    },

    getDivElemStandard: function( divname ){
      var elem = CNodes.getElem( 'div', divname, 'absolute', 'block',
                               0, 0, this.width, this.height );
      return elem;
    },

    addDivElem: function( divname, parentelem ){
      if ( $( divname ) ) alert( 'Element with id="' + divname + '" already existing');
      else {
        var elem = this.getDivElemStandard( divname );
        parentelem.appendChild(elem);
        return $( divname );
      }
      return null;
    },

    getCanvasElemStandard: function( canvasname ){
      var elem = CNodes.getElem( 'canvas', canvasname, 'absolute', 'block',
                               0, 0, this.width, this.height );
      elem.appendChild(document.createTextNode("CANVAS NOT AVAILABLE"));
      return elem;
    },

    addCanvasElem: function( canvasname, parentelem ){
      if ( $( canvasname ) ) alert( 'Element with id="' + canvasname + '" already existing');
      else {
        var elem = this.getCanvasElemStandard( canvasname );
        parentelem.appendChild(elem);
        if( typeof G_vmlCanvasManager != 'undefined' ) G_vmlCanvasManager.initElement(elem);
        return $( canvasname );
      }
      return null;
    },

    getElemName: function( shortname ){
      return 'CLookStopDrawer_' + this.referencecount + '_' + shortname;
    }
  }

  //##############################################################################################
  //### Concrete Stop Drawers ####################################################################
  //##############################################################################################


  var CLookStopDrawerChain = Class.create();
  CLookStopDrawerChain.prototype = Object.extend( new ALookStopDrawer(), {
    // constructor
    initialize: function() {
      this.referencecount = gLookStopDrawerReferenceCount;
      gLookStopDrawerRegistry[this.referencecount] = this;
      gLookStopDrawerReferenceCount++;
    },
    drawallstops: function( transformer, stops, showstopnames, showstoptimes ){
      var x = 0;
      var y = 0;
      this.stopradius = this.getStopRadius( stops.length);
      for (var i = 0; i < stops.length; i++) {
        if( stops[i] ){
          x = transformer.getX(stops[i].x, stops[i].y);
          y = transformer.getY(stops[i].x, stops[i].y);
          this.drawstop(x,y,stops[i]);
          this.drawstopdetails(x,y,stops[i]);
          if( ( showstopnames == 'all' ) ||
              ( showstopnames == 'some' && stops[i].count!=2 ) ||
              ( showstopnames == 'few' && stops[i].count==1 ) ||
              ( showstopnames != 'no' && stops[i].termstop=="yes" ) ||
              ( showstopnames != 'no' && stops[i].startstop=="yes" ) ){
            this.drawstopname(x,y,stops[i]);
          }
          if( ( showstoptimes == 'all' ) ||
              ( showstoptimes == 'some' && stops[i].count!=2 ) ||
              ( showstoptimes == 'few' && stops[i].count==1 ) ){
            var stoptime = "";
            if ( stops[i].dep != "" && stops[i].arr != "") {
              if (stops[i].dep == stops[i].arr) {
                //stoptime = 'an/ab ' + stops[i].dep;
                stoptime = stops[i].dep;
              }else{
                //stoptime = 'an ' + stops[i].arr + ' / ab ' + stops[i].dep;
                stoptime = stops[i].arr + ' / ' + stops[i].dep;
              }
            } else if (stops[i].dep != ""){
              //stoptime = 'ab ' + stops[i].dep;
              stoptime = stops[i].dep;
            } else if (stops[i].arr != ""){
              //stoptime = 'an ' + stops[i].arr;
              stoptime = stops[i].arr;
            }
            if( stoptime != "" ) this.drawstoptime(x,y,stoptime);
          }
        }
      }
    },
    drawstopname:function(x,y,stop){
      this.drawtextontextdiv(x,y,stop.name,"left");
    },
    drawstoptime:function(x,y,text){
      this.drawtextontextdiv(x,y,text,"right");
    }
  });

  var CLookStopDrawerNetspider = Class.create();
  CLookStopDrawerNetspider.prototype = Object.extend( new CLookStopDrawerChain(), {
    // constructor
    initialize: function() {
      this.referencecount = gLookStopDrawerReferenceCount;
      gLookStopDrawerRegistry[this.referencecount] = this;
      gLookStopDrawerReferenceCount++;
    },
    drawallstops: function( transformer, stops, showstopnames, showstoptimes ){
      var x = 0;
      var y = 0;
      this.stopradius = this.getStopRadius( stops.length);
      for (var i = 0; i < stops.length; i++) {
        if( stops[i] ){
          x = transformer.getX(stops[i].x, stops[i].y);
          y = transformer.getY(stops[i].x, stops[i].y);
          if(i==0){
            this.drawinitialstop(x,y,stops[i]);
            this.drawstopname(x,y,stops[i]);
          }else{
            this.drawstop(x,y,stops[i]);
            this.drawstopdetails(x,y,stops[i]);
            if( ( showstopnames == 'all' ) ||
                ( showstopnames == 'some' && stops[i].count!=2 ) ||
                ( showstopnames == 'few' && stops[i].count==1 ) ||
                ( showstopnames != 'no' && stops[i].termstop=="yes" ) ||
                ( showstopnames != 'no' && stops[i].startstop=="yes" ) ){
              this.drawstopname(x,y,stops[i]);
            }
          }
          if( ( showstoptimes == 'all' ) ||
              ( showstoptimes == 'some' && stops[i].count!=2 ) ||
              ( showstoptimes == 'few' && stops[i].count==1 ) ){
            var stoptime = "";
            if ( stops[i].dep != "" && stops[i].arr != "") {
              if (stops[i].dep == stops[i].arr) {
                //stoptime = 'an/ab ' + stops[i].dep;
                stoptime = stops[i].dep;
              }else{
                //stoptime = 'an ' + stops[i].arr + ' / ab ' + stops[i].dep;
                stoptime = stops[i].arr + ' / ' + stops[i].dep;
              }
            } else if (stops[i].dep != ""){
              //stoptime = 'ab ' + stops[i].dep;
              stoptime = stops[i].dep;
            } else if (stops[i].arr != ""){
              //stoptime = 'an ' + stops[i].arr;
              stoptime = stops[i].arr;
            }
            if( stoptime != "" ) this.drawstoptime(x,y,stoptime);
          }
        }
      }
    },
    drawinitialstop: function (x,y,stop){
      if (this.stopcanvas.getContext){
        var ctx = this.stopcanvas.getContext('2d');
        ctx.save();
        ctx.translate(x+0.5,y+0.5);
        var colarray = help.getproductclasscolours( stop.prodclass );
        ctx.beginPath();
        ctx.fillStyle = "rgba(0,0,0,0.15)";
        ctx.arc(0,0,this.stopradius+2+colarray.length*1,0,Math.PI*2.0,true);
        ctx.fill();
        for( var p = 0, dia = colarray.length-1; p < colarray.length ; p++, dia-- ){
          ctx.beginPath();
          ctx.fillStyle = colarray[p];
          ctx.arc(0,0,this.stopradius+2+dia*1,0,Math.PI*2.0,true);
          ctx.fill();
        }
        ctx.beginPath();
        ctx.fillStyle = "rgba(0,0,0,1)";
        ctx.arc(0,0,this.stopradius+1,0,Math.PI*2.0,true);
        ctx.fill();
        ctx.restore();
      } else {
        alert( "Canvas Context not found" );
      }
    }
  });

  var CLookStopDrawerPerl = Class.create();
  CLookStopDrawerPerl.prototype = Object.extend( new ALookStopDrawer(), {
    // constructor
    initialize: function() {
      this.referencecount = gLookStopDrawerReferenceCount;
      gLookStopDrawerRegistry[this.referencecount] = this;
      gLookStopDrawerReferenceCount++;
    },
    drawallstops: function( transformer, stops, maxstopcol, showstopnames, showstoptimes ){
      var x = 0;
      var y = 0;
      this.stopradius = 4;
      for (var i = 0; i < stops.length; i++) {
        if( stops[i] ){
          x = transformer.getX(stops[i].x, stops[i].y);
          y = transformer.getY(stops[i].x, stops[i].y);
          this.drawstop(x,y,stops[i]);
          this.drawstopdetails(x,y,stops[i]);
          if( ( showstopnames == 'all' ) ||
              ( showstopnames == 'some' && stops[i].count!=2 ) ||
              ( showstopnames == 'few' && stops[i].count==1 ) ){
            this.drawstopname(x,y,stops[i],maxstopcol[stops[i].row]);
          }
          if( ( showstoptimes == 'all' ) ||
              ( showstoptimes == 'some' && stops[i].count!=2 ) ||
              ( showstoptimes == 'few' && stops[i].count==1 ) ){
            var stoptime = "";
            if ( stops[i].dep != "" && stops[i].arr != "") {
              if (stops[i].dep == stops[i].arr) {
                //stoptime = 'an/ab ' + stops[i].dep;
                stoptime = stops[i].dep;
              }else{
                //stoptime = 'an ' + stops[i].arr + ' / ab ' + stops[i].dep;
                stoptime = stops[i].arr + ' / ' + stops[i].dep;
              }
            } else if (stops[i].dep != ""){
              //stoptime = 'ab ' + stops[i].dep;
              stoptime = stops[i].dep;
            } else if (stops[i].arr != ""){
              //stoptime = 'an ' + stops[i].arr;
              stoptime = stops[i].arr;
            }
            if( stoptime != "" ) this.drawstoptime(x,y,stoptime);
          }
        }
      }
    },
    drawstopname:function(x,y,stop,maxcol){
      if( stop.col == 0 )
        this.drawtextontextdiv(x,y,stop.name,"right");
      else if( stop.col == maxcol )
        this.drawtextontextdiv(x,y,stop.name,"left");
    },
    drawstoptime:function(x,y,text){
      this.drawtextontextdiv(x,y,text,"left");
    }
  });

  var CLookStopDrawerMap = Class.create();
  CLookStopDrawerMap.prototype = Object.extend( new ALookStopDrawer(), {
    // constructor
    initialize: function() {
      this.referencecount = gLookStopDrawerReferenceCount;
      gLookStopDrawerRegistry[this.referencecount] = this;
      gLookStopDrawerReferenceCount++;
    },
    clearAllDivs: function(){
      this.clearCanvasDiv();
      CNodes.removeAllChilds( this.textdiv );
      CNodes.removeAllChilds( this.detailsdiv );
      CNodes.removeAllChilds( this.mousediv );
      this.mousemanager.removeKind('2_look_stop')
    },
    drawallstops: function( transformer, stops, showstopnames ){
      this.setTransformer( transformer );
      this.firststoptodraw = 0;
      this.stopdrawpart = 0;
      this.stops = stops;
      this.showstopnames = showstopnames;
      if( this.aktiv ){
        this.aktiv.stop();
        delete this.aktiv;
      }
      this.aktiv = new PeriodicalExecuterForObjects(this, 1);
      this.callback();
    },
    callback: function(){
      if( this.drawallstopswhenpossible() == 'finished' ){
        if( this.aktiv ){
          this.aktiv.stop();
          delete this.aktiv;
        }
      }
    },
    drawallstopswhenpossible: function(){
      var x = 0;
      var y = 0;
      var before = (new Date()).getTime();
      this.stopradius = this.getStopRadius( this.stops.length);
      if( this.stopdrawpart == 0 ){
        for (var i = this.firststoptodraw; i < this.stops.length; i++) {
          if( (new Date()).getTime() - before > 300 ){
            // Lasts too long, break here...
            this.firststoptodraw = i;
            this.stopdrawpart = 0;
            //CLookStatus.show( i+' of '+this.stops.length+' stops shown' );
            return 'not finished';
          }
          if( this.stops[i] ){
            this.stops[i].calcx = Math.round( this.getTransformer().getX(this.stops[i].x, this.stops[i].y) );
            this.stops[i].calcy = Math.round( this.getTransformer().getY(this.stops[i].x, this.stops[i].y) );
            this.drawstop(this.stops[i].calcx,this.stops[i].calcy,this.stops[i]);
            this.drawstopdetails(this.stops[i].calcx,this.stops[i].calcy,this.stops[i]);
          }
        }
        this.stopdrawpart = 1;
        this.firststoptodraw = 0;
      }
      if( this.stopdrawpart == 1 ){
        if( this.showstopnames == true ){
          for (var i = this.firststoptodraw; i < this.stops.length; i++) {
            if( (new Date()).getTime() - before > 300 ){
              // Lasts too long, break here...
              this.firststoptodraw = i;
              this.stopdrawpart = 1;
              CLookStatus.show( i+' of '+this.stops.length+' stop names shown' );
              return 'not finished';
            }
            if( this.stops[i] ){
              this.drawstopname(this.stops[i].calcx,this.stops[i].calcy,this.stops[i]);
            }
          }
        }
        this.stopdrawpart = 2;
        this.firststoptodraw = 0;
      }
      //CLookStatus.show( i+' stops shown' );
      return 'finished';
    },
    drawstopdetails: function(x,y,stop){
      var mx = Math.round(x);
      var my = Math.round(y);
      var name = '';
      var extId = 0;

      if( stop.name ) name = stop.name;
      if( stop.extId ) extId = stop.extId;

      if( this.mousemanager ){
        this.mousemanager.addElem({kind:'2_look_stop',
                                   x:mx,y:my,
                                   radius:5,
                                   title:name,
                                   extId:extId,
                                   titleClassName:'look_popup_title_stop',
                                   icon:gImagePath + 'look/stoppopup.gif',
                                   bodyfunction:'stboard',
                                   startlocation:true,
                                   destination:true
                                   });
      }else alert('Mousemanager missing');
    },
    drawstopname:function(x,y,stop){
      this.drawtextontextdiv(x,y,stop.name,"left");
    }
  });


  var CLookPoiDrawerMap = Class.create();
  CLookPoiDrawerMap.prototype = Object.extend( new ALookStopDrawer(), {
    // constructor
    initialize: function( poiclass ) {
      this.referencecount = gLookStopDrawerReferenceCount;
      gLookStopDrawerRegistry[this.referencecount] = this;
      gLookStopDrawerReferenceCount++;
      this.poiclass = poiclass;
      this.iconsize = 10;
      this.mousoversize = 12;
    },
    // initialization
    init: function( aStopDivContainer, aDetailsDivContainer, aMouseDivContainer, aWidth, aHeight ) {
      this.width = aWidth;
      this.height = aHeight;
      this.initializeCanvasDiv(aStopDivContainer);
      this.initializeDetailsDiv(aDetailsDivContainer);
      this.initializeMouseDiv(aMouseDivContainer);
    },

    initializeCanvasDiv: function( divcontainer ) {
      this.stopdiv = this.addDivElem( this.getElemName( 'StopDiv' ), divcontainer );
    },
    clearAllDivs: function(){
      this.clearCanvasDiv();
      CNodes.removeAllChilds( this.detailsdiv );
      CNodes.removeAllChilds( this.mousediv );
      this.mousemanager.removeKind('3_look_poi_'+this.poiclass)
    },
    clearCanvasDiv: function() {
      CNodes.removeAllChilds( this.stopdiv );
    },
    drawallstops: function( transformer, stops ){
      var x = 0;
      var y = 0;
      this.stopradius = this.getStopRadius( stops.length);
      for (var i = 0; i < stops.length; i++) {
        if( stops[i] ){
          x = (this.iconsize+2) * Math.round(( transformer.getX(stops[i].x, stops[i].y))/(this.iconsize+2));
          y = (this.iconsize+2) * Math.round(( transformer.getY(stops[i].x, stops[i].y))/(this.iconsize+2));
          this.drawstop(x,y);
          this.drawstopdetails(x,y,stops[i]);
        }
      }
      //CLookStatus.show( stops.length+' pois shown' );
    },
    drawstop: function (x,y){
      if( typeof gImagePath == 'undefined' ) alert( 'ALookStopDrawer::drawinfo: gImagePath not set' );
      if (this.stopdiv){
        var elem = document.createElement('img');
        elem.style.position = 'absolute';
        elem.style.display = 'block';
        elem.style.left = (x - (this.iconsize/2)).toString() + 'px';
        elem.style.top = (y - (this.iconsize/2)).toString() + 'px';
		  if( gPOIDATA[this.poiclass] ){
			 elem.width= gPOIDATA[this.poiclass].mapiconwidth;
			 elem.height= gPOIDATA[this.poiclass].mapiconheight;
			 elem.src= gPOIDATA[this.poiclass].mapiconimgsrc;
		  }else{
			 elem.width= this.iconsize;
			 elem.height= this.iconsize;
			 elem.src= gImagePath + 'look/poi' + this.poiclass + 'map.gif';
		  }
        this.stopdiv.appendChild(elem);
      }
    },
    drawstopdetails: function(x,y,stop){
      var name = '';
      if( stop.name ) name = stop.name;
      // mouseover for poi on map
      if( this.mousemanager ){
		  var icon = '';
  		  if( gPOIDATA[this.poiclass] ){
		    icon = gPOIDATA[this.poiclass].mapiconimgsrc;
		  }else{
			 icon = gImagePath + 'look/poi' + this.poiclass + 'map.gif';
		  }
		  this.mousemanager.addElem({kind:'3_look_poi_'+this.poiclass,
                                   x:x,y:y,
                                   radius:Math.round(this.mousoversize/2),
                                   title:name,
                                   icon:icon,
                                   titleClassName:'look_popup_title_poi',
                                   startlocation:true,
                                   destination:true
                                   });
      }
    },
    showdetails: function(x,y,name,text){
      var ddiv = document.createElement('div');
      ddiv.className = "look_details";
      ddiv.style.top = Math.round(y - 8) + 'px';
      ddiv.style.left = Math.round(x + 20) + 'px';

      var titlediv = document.createElement('div');
      titlediv.className = "look_details_title";

      var poiimg = document.createElement('img');
		if( gPOIDATA[this.poiclass] ){
		  poiimg.width= gPOIDATA[this.poiclass].mapiconwidth;
		  poiimg.height= gPOIDATA[this.poiclass].mapiconheight;
		  poiimg.src= gPOIDATA[this.poiclass].mapiconimgsrc;
		}else{
		  poiimg.width= this.iconsize;
		  poiimg.height= this.iconsize;
		  poiimg.src= gImagePath + 'look/poi' + this.poiclass + 'map.gif';
		}

      var titletext = document.createElement('span');
      titletext.className = "look_details_titletext";
      titletext.innerHTML = name;

      titlediv.appendChild(poiimg);
      titlediv.appendChild(titletext);

      var bodydiv = document.createElement('div');
      bodydiv.className = "look_details_body";
      bodydiv.innerHTML = text;

      ddiv.appendChild(titlediv);
      ddiv.appendChild(bodydiv);

      this.detailsdiv.appendChild( ddiv );
    }
  });



  //##############################################################################################
  //### Abstract Edge Drawer #####################################################################
  //##############################################################################################

  var ALookEdgeDrawer = Class.create();
  ALookEdgeDrawer.prototype= {
    initialize: function(){},

    drawalledges: function(canvas,transformer,stops,edges){
      var id1, id2;
      this.currentcanvas = canvas;
      this.transformer = transformer;
      for (var i = 0; i < edges.length; i++) {
        if( edges[i] ){
          id1 = edges[i].id1;
          id2 = edges[i].id2;
          this.drawedge(stops[id1].x,stops[id1].y,stops[id2].x,stops[id2].y,edges[i]);
        }
      }
    },

    canvasmoveTo: function (ctx, x, y){
      ctx.moveTo(this.transformer.getX(x,y),this.transformer.getY(x,y));
    },

    canvaslineTo: function (ctx, x, y){
      ctx.lineTo(this.transformer.getX(x,y),this.transformer.getY(x,y));
    }
  }

  //##############################################################################################
  //### Concrete Edge Drawers ####################################################################
  //##############################################################################################

  var CLookEdgeDrawerChain = Class.create();
  CLookEdgeDrawerChain.prototype= Object.extend(new ALookEdgeDrawer(), {

    drawedge: function (mx1,my1,mx2,my2,edge){
      if (this.currentcanvas.getContext){
        var ctx = this.currentcanvas.getContext('2d');
        var colarray = help.getproductclasscolours( edge.prodclass );
        var transx = 0;
        var transy = 0;
        var x1 = this.transformer.getX(mx1,my1);
        var y1 = this.transformer.getY(mx1,my1);
        var x2 = this.transformer.getX(mx2,my2);
        var y2 = this.transformer.getY(mx2,my2);
        // grey shadow to get better contrast
        ctx.lineWidth = Math.min(4, 2 + colarray.length).toString();
        ctx.beginPath();
        ctx.strokeStyle = "rgba(0,0,0,0.15)";
        ctx.moveTo( x1, y1 );
        ctx.lineTo( x2, y2 );
        ctx.stroke();

        ctx.lineWidth = "2";
        if( colarray.length > 1 ){
          var divisor = Math.sqrt((y1-y2)*(y1-y2)+(x2-x1)*(x2-x1));
          transx = (y1-y2)/divisor;
          transy = (x2-x1)/divisor;
          ctx.lineWidth = "1";
        }
        for( var p = 0; p < colarray.length ; p++ ){
          ctx.beginPath();
          ctx.strokeStyle = colarray[p];
          ctx.moveTo( x1+transx*p*1, y1+transy*p*1 );
          ctx.lineTo( x2+transx*p*1, y2+transy*p*1 );
          ctx.stroke();
        }
      }
    }
  });

  var CLookEdgeDrawerPerl = Class.create();
  CLookEdgeDrawerPerl.prototype= Object.extend(new ALookEdgeDrawer(), {

    drawedge: function (mx1,my1,mx2,my2,edge){
      if (this.currentcanvas.getContext){
        var edgex = edge.col
        var ctx = this.currentcanvas.getContext('2d');
        ctx.strokeStyle = "rgba(255,0,0,1)";
        ctx.lineWidth = "2";
        ctx.lineJoin = "round";
        ctx.beginPath();
        this.canvasmoveTo( ctx, mx1, my1 );
        for( var y = parseInt(my1)+1 ; y < parseInt(my2); y++ ){
          this.canvaslineTo( ctx, edgex, y );
        }
        this.canvaslineTo( ctx, mx2, my2 );
        ctx.stroke();
      }
    }
  });
}


