import java.util.*;
import java.io.*;

public class Collector implements Runnable {
  Vector runners;
  TelemetryServerConnection tsc;
  LocationImages li;

  public static void main (String args[]) {
    (new Collector(args)).run();
  }

  public void generateSummaries() {
    int ct;
    long minTime;
    long summaryIncrement = 300000; /* 1000*60*5 = 5 minutes */
    Enumeration rs;
    Runner r;

//    if( ((Runner) runners.elementAt(0)).dataset[0].history.size() == 0)
//	return;

//    minTime = ((RunnerData) ((((Runner) runners.elementAt(0)).dataset[0]).history).elementAt(0)).timestamp;

    rs = runners.elements();
    while(rs.hasMoreElements()){
      r = (Runner) rs.nextElement();
      for(ct=0;ct<Runner.datatypes;ct++){
	r.summary[ct] = summarize(r.dataset[ct], 0, summaryIncrement);
	System.out.println("Runner "+r.name+" field "+ct);
	if(r.summary[ct] != null)
		r.summary[ct].type = ct;
      }
    }
    
  }

  public RunnerHistory summarize(RunnerHistory raw, long tmin, long inc){
    Enumeration p;
    RunnerData d;
    double average, max, min, rtot;
    double timeavg, rtime, timemin, timemax;
    RunnerHistory shist = new RunnerHistory(0);
    int tmp, bin, count;

    p = (raw.history).elements();
    bin = 0;
    rtot=rtime=0;
    timemin = min = -1;
    timemax = max = 0;
    count = 0;
	if(raw.history.size() == 0)
		return null;
    System.out.println("Summarizing "+raw.history.size()+" datapoints");
    while(p.hasMoreElements()){
      d = (RunnerData) p.nextElement();
      tmp = ((int) ((d.timestamp-tmin)/inc));
      if(bin != tmp){
	average = ((double) rtot)/((double) count);
	timeavg = ((double) rtime)/((double) count);
	if((bin+1) > shist.history.size())
	  shist.history.setSize(bin+1);
	shist.history.setElementAt(new RunnerData((long) ((bin+.5)*inc), // Or, timeavg 
					      (long) ((bin+1)*inc),  // Or, timemax
					      (long) (bin*inc), // or, timemin
					  average, max, min),
			   bin);
	rtot=0;
	min = -1;
	max = 0;
	count = 0;
      }
      rtot += d.value;
      rtime += d.timestamp;
      count++;

      if(min > 0)
	min = (d.value < min) ? d.value:min;
      else
	min = d.value;

      if(timemin > 0)
	timemin = (d.timestamp < timemin) ? d.timestamp:timemin;
      else
	timemin = d.timestamp;

      timemax = (d.timestamp > timemax) ? d.timestamp:timemax;

      bin = tmp;
    }

    average = ((double) rtot)/((double) count);
    timeavg = ((double) rtime)/((double) count);
    if((bin+1) > shist.history.size())
      shist.history.setSize(bin+1);
    shist.history.setElementAt(new RunnerData((long) timeavg, 
					      (long) ((bin+1)*inc),  // Or, timemax
					      (long) (bin*inc), // or, timemin
					      average, max, min),
			   bin);
    return shist;
  }

  void dumpSummaries() {
    Enumeration rs;
    Runner r;
    File d;
    PrintStream pout;
    int ct, row, bestData, bestSize;

    try {
    pout = new PrintStream(new FileOutputStream(new File("/tmp/runners.dat")));
    } catch (Exception e) { 
      System.out.println("Couldn't open dump file: "+e);
      return;
    }

    rs = runners.elements();
    while(rs.hasMoreElements()){
      r = (Runner) rs.nextElement();
      pout.println("RUNNER "+r.name.toUpperCase());
	bestSize = bestData =0;
	for(ct=0;ct<Runner.datatypes;ct++){
		if(r.summary[ct] != null){
			if(r.summary[ct].history.size() >bestSize){
				bestSize = r.summary[ct].history.size();
				bestData=ct;
			}
		}
	}
      if(r.summary[bestData] == null) {
	return;
	}
      System.out.println("Outputting "+r.summary[bestData].history.size()+" rows for "+r.name);
      for(row=0;row<(r.summary[bestData].history.size());row++){
	if(r.summary[bestData].history.elementAt(row) == null)
	  continue;
	pout.print(((RunnerData) ((r.summary[bestData]).history).elementAt(row)).timestamp+":"+
		   ((RunnerData) ((r.summary[bestData]).history).elementAt(row)).timemax+":"+
		   ((RunnerData) ((r.summary[bestData]).history).elementAt(row)).timemin+" ");
	for(ct=0;ct<Runner.datatypes;ct++) {
	  if(r.summary[ct] == null){
	    pout.print("-1:-1:-1 ");
	    continue;
	  }
	  if(row >= r.summary[ct].history.size()){
	    pout.print("-1:-1:-1 ");
	    continue;
	  }
	  if(r.summary[ct].history.elementAt(row) == null) {
	    pout.print("-1:-1:-1 ");
	    continue;
	  }
	  pout.print(
		     ((RunnerData) r.summary[ct].history.elementAt(row)).value+":"+
		     ((RunnerData) r.summary[ct].history.elementAt(row)).plus+":"+
		     ((RunnerData) r.summary[ct].history.elementAt(row)).minus+" ");
	}

	if(r.summary[0] != null && r.summary[1]!=null){
	  if((r.summary[0].history.size() > (row+1)) &&
	     (r.summary[1].history.size() > (row+1))){
	    pout.print(li.nearest(((RunnerData) r.summary[0].history.elementAt(row)).value,
				  (((RunnerData) r.summary[1].history.elementAt(row)).value)));
	  }
	}
	pout.print("\n");
      }
      pout.print("\n");
    }

    pout.println("CONTROL");
    pout.println("NEXTREQUEST 60");
  }

  Collector (String runnernames[]) {
    int ct;

    // Identify the telemetry server
	 tsc = new TelemetryServerConnection(runnernames[0],
					     Integer.parseInt(runnernames[1]));

	li = new LocationImages(runnernames[2]);
	li.load();
    // Create the runners
    runners = new Vector();
    for(ct=3;ct<runnernames.length;ct++){
      runners.addElement(new Runner(runnernames[ct]));
    }

	

  }


  public void run() {
    int ct;
    Enumeration runnerList,telemetryData;
    Runner curRunner;
    long lastDump;
    RunnerData curData;

    // Get this historical data for each of the runners
    lastDump = 0;					   
    while(true){
      for(runnerList = runners.elements();	
	  runnerList.hasMoreElements();
	  ){
	curRunner=(Runner) runnerList.nextElement();
	for(ct=0;ct<Runner.datatypes;ct++){
	  telemetryData = ((tsc.request(curRunner.name, 
				       Runner.datanames[ct], 
				       curRunner.mostRecentData[ct])).elements());
	  if(telemetryData != null) {
	    for(;
		telemetryData.hasMoreElements();
		){
	      curData=(RunnerData) telemetryData.nextElement();

	      curRunner.add(ct, curData);
	      curRunner.mostRecentData[ct] = (curData.timestamp > curRunner.mostRecentData[ct]) ? 
		curData.timestamp:curRunner.mostRecentData[ct];

	    }
	  }
	}
      }

      if(System.currentTimeMillis() > (lastDump + (1000*10))){
	System.out.println("Dumping data...");
	generateSummaries();
	dumpSummaries();
	lastDump = System.currentTimeMillis();
      }
	else {
		try {Thread.sleep(5000); } catch (Exception e) { }
	}

    }
  }

}
