// Copyright 2006 comparetracks.com 
// Written by Terje Henriksen 
// Copy, modification or reuse of code is herby granted 

Runner = function(name, folder, startno, startTime, expectedAtFirstSplit) {	
    this.name = name;
    this.folder = folder;
    this.startno = startno;
    this.expectedAtFirstSplit = parseInt(expectedAtFirstSplit);
    this.indexno = 0;
    this.ballImage = null;
    this.googleIcon = null;
    this.marker = null;
    this.startTime = parseInt(startTime);
    this.lat = 0;
	  this.lon = 0;
	  this.splits = new Array();
	  this.serverMessage = "";

	  this.state = "NotStarted";
    this.simFinishedSSM = 0;
	  this.lastReportedSSM =0;
	  this.nextReportSSM =0;
    this.lastReportedSplit = null;
    this.nextReportSplit = null;
   
	  this.nextRequestSSM =0;
	  this.lastRequestSSM =0;

    this.computePosition = computePosition;
    this.setIndexNo = setIndexNo;
    this.moveMarker = moveMarker;
    this.description = description;

    function computePosition(route,secSinceMidnight) {

      // Check if not inited
      if(this.splits == null || this.splits.length == 0) {
        return;
      }

      // Check not started
      if(secSinceMidnight <= this.startTime) { 
        this.lat = route.trackPoints[0].lat;
        this.lon = route.trackPoints[0].lon;
        this.state = "NotStarted";
        this.simFinishedSSM = this.startTime + route.splitPoints[route.splitPoints.length-1].seconds;
		    this.nextRequestSSM = this.startTime + route.splitPoints[0].seconds - 300;  // 5 min before expected at first split
        this.nextReportSSM = this.startTime + route.splitPoints[0].seconds;
        return;
      }

      var splitNo = this.splits.length;  
	    var secondsSinceStart = secSinceMidnight-this.startTime;
	    if(secondsSinceStart < 0)
	      secondsSinceStart = 0;
		
      var simSec = secondsSinceStart;
      var fact=1.0;
	    var reportTime =0;

	  
	  // Get last reported time
	  this.lastReportedSplit = null;
      
	  for(var i=0; i<splitNo; i++) {
 	    reportTime = parseInt(this.splits[i]);

	    if(reportTime > 0) {
        this.lastReportedSplit = route.splitPoints[i];
		    if(i == splitNo-1)  {
          var j = route.trackPoints.length -1;
          this.lat = route.trackPoints[j].lat;
          this.lon = route.trackPoints[j].lon;
          this.alt = route.trackPoints[j].alt;
			    this.simFinishedSSM = reportTime + this.startTime; 
          this.state = "Finished"; 
          this.nextRequestSSM = secSinceMidnight + 5*3600; 
          return;
        }
		    fact = reportTime/route.splitPoints[i].seconds;
		    this.lastReportedSSM = this.startTime + reportTime;
        this.nextReportSplit = route.splitPoints[i+1];
      } 
    }
    if(this.lastReportedSplit == null) {
      this.nextReportSplit = route.splitPoints[0];
      if(this.expectedAtFirstSplit != 0) {
 		    fact = this.expectedAtFirstSplit/route.splitPoints[0].seconds;
      }
    }
    
    // Compute next report
    var simSec = this.nextReportSplit.seconds*fact - secondsSinceStart;
    if(simSec < 0) {
      simSec *= -1;
		  //this.nextReportSSM = simSec;
      //$this->description .= '<tr><td>Should have reported at:</td><td>'.$nextReport->desc.'</td><td>'.CompareTracks::PrintMinutes($simSec).' ago</td></tr>';
      
      fact = secondsSinceStart/this.nextReportSplit.seconds;
      this.simFinishedSSM = route.splitPoints[splitNo-1].seconds*fact + this.startTime;  
      //var fromNow = this.simFinished - this.secondsSinceStart;
      //$this->description .= '<tr><td>Estimated finish time:</td><td>'.CompareTracks::PrintFullTime($this->simFinished).'</td><td>('.CompareTracks::PrintMinutes($fromNow).' from now)</td></tr>';
      
        this.lat = this.nextReportSplit.lat;
        this.lon = this.nextReportSplit.lon;
        this.alt = this.nextReportSplit.alt;
        this.state = "Overdue";  
        this.nextRequestSSM = this.lastRequestSSM+60;  
        this.nextReportSSM = secSinceMidnight-simSec; 
        return;
      }
    
      //$this->description .= '<tr><td>Expected next report:</td><td>'.$nextReport->desc. '</td><td>'.CompareTracks::PrintMinutes($simSec).' from now</td></tr>';
      this.state = "Approaching";
      //this.nextRequestSSM = secSinceMidnight+simSec;        
      //this.nextReportSSM = secSinceMidnight+simSec;  this.nextReportSplit.seconds*fact      
      this.nextRequestSSM = this.nextReportSplit.seconds*fact + this.startTime;       
      this.nextReportSSM = this.nextReportSplit.seconds*fact + this.startTime;      
   
      // Compute finish time
      this.simFinishedSSM = route.splitPoints[splitNo-1].seconds*fact + this.startTime; 
      //$fromNow = $this->simFinished - $this->secondsSinceStart;
      //$this->description .= '<tr><td>Estimated finish time:</td><td> '.CompareTracks::PrintFullTime($this->simFinished).'</td><td>('.CompareTracks::PrintMinutes($fromNow).' from now)</td></tr>';
        
      var prev = route.trackPoints[0];
      var next = null;

      simSec = secondsSinceStart/fact;
      for(var i=0;i<route.trackPoints.length;i++) {
        if(route.trackPoints[i].seconds > simSec) {
          next = route.trackPoints[i];
          break;
        }
        prev = route.trackPoints[i];
      }
    
      // Interpolate
      if(next != null) {
        var secFact = (simSec - prev.seconds)/(next.seconds-prev.seconds);
        this.lat = (next.lat - prev.lat)*secFact + prev.lat;
        this.lon = (next.lon - prev.lon)*secFact + prev.lon;
      }
      else {
        this.lat = prev.lat;
        this.lon = prev.lon;
        this.alt = prev.alt;
      }
    }

    function description(route,secondsSinceMidnight) {
      //var ret = "<b>" + this.name + "</b> (" + this.startno + " " + this.expectedAtFirstSplit + ")<br>";
      var ret = "<b>" + this.name + "</b> (" + this.startno + ")<br>";
      if(this.state == "NotStarted") {
        ret += "Will start at: " + communicator.getClientTimeString(this.startTime,false) + "<br>Expected first report from " + route.splitPoints[0].name;
        if(this.expectedAtFirstSplit != 0) 
          ret += " ca " + communicator.getClientTimeString(this.startTime + this.expectedAtFirstSplit,false);
        else
          ret += " ca " + communicator.getClientTimeString(this.startTime + route.splitPoints[0].seconds,false);
        return ret;
      }
      if(this.state == "Finished") {
        ret += "Finished at: " +  communicator.getTimeString(this.simFinishedSSM - this.startTime,true);
        return ret;
      }
      if(this.state == "Overdue") {
        //ret += "Should have reported from : " +  this.nextReportSplit.name  + "  " + getClientTimeString(this.nextReportSSM,false) + "<br>";
        ret += "Should have reported from: " +  this.nextReportSplit.name  + "  " + communicator.printTimeDiff(this.nextReportSSM) + "<br>";
        if(this.lastReportedSplit != null)
          ret += "New expected finish time: " +  communicator.getTimeString(this.simFinishedSSM - this.startTime,true);
        return ret;
      }

      if(this.lastReportedSplit != null) {
        var secAgo = communicator.printTimeDiff(this.lastReportedSSM);
        ret += "Last reported from " + this.lastReportedSplit.name  + "  " + secAgo + "<br>";
      }
      ret += "Expected next report from " + this.nextReportSplit.name + " ca " + communicator.getClientTimeString(this.nextReportSSM,false) + "<br>";

      if(this.lastReportedSplit != null)
        ret += "Expected Finish time: " +  communicator.getTimeString(this.simFinishedSSM - this.startTime,true);
      return ret;     
    }

    function setIndexNo(inx) {
      this.indexno = inx; 
      this.ballImage = "http://www.sportsim.com/splitLive/images/ball" + inx + ".gif";
      this.googleIcon = new GIcon();
      this.googleIcon.image = this.ballImage; 
      this.googleIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
      this.googleIcon.iconSize = new GSize(16, 16);
      this.googleIcon.shadowSize = new GSize(16, 16);
      this.googleIcon.iconAnchor = new GPoint(8, 8);
      this.googleIcon.infoWindowAnchor = new GPoint(8,8);
      this.marker = new GMarker(new GLatLng(this.lat,this.lon),this.googleIcon);

      GEvent.addListener(this.marker, 'click', function() {
        selectMarker(inx);
      });       

    }

    function moveMarker() {
      var pp = this.marker.getPoint();
      if(pp.lat() != this.lat || pp.lng() != this.lon) 
        this.marker.setPoint(new GLatLng(this.lat,this.lon));
    }
  };
