package edu.vt.marian.common;

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



/** Used to measure system performance,
		this can be used mutiple times.  It will caculate the 
		average, and dump all the results to a file in human readable format.
	@author: Jianxin Zhao
	<P>Finished time: ????, 1999
	<P>Known bugs: none
	<P>Platform: jdk1.1.7 under WINDOW 95
*/

public class Measurement
{
	/** possible return values of methods
	*/
	public final static int OK = 0;
	public final static int WRONG_STATE = 1;

	/** this is the description of this object
	*/
	private String description = null;

	/** this vector contains all the data of all the this Measurement 
	*/
	private Vector measures = new Vector();

	/** this flag will indicate currently whether or not we are waiting for
		the end measure
	*/
	private boolean state = false;

	/** this constructor will create a PerformanceMeasurement object, there is no
		Measurement at this time
	*/
	public Measurement(String des)
	{
		description = des;
	}


	/** this will add a new measurement into this object, the return value is the id of
		this measurement and can be used to do measure later
	*/
	public int start(long time)
	{
		if (state)
		{
			// we are waiting for a end measure
			System.err.println("class Measurement, method start, wrong state");
			return WRONG_STATE;
		}

		// add this to the measures vector
		measures.addElement(new Long(time));
		state = true;
		return OK;
	}


	/** this method will record a start time for the measurement specified by the 
		parameter measurement_id
	*/
	public int end(long time)
	{
		if (! state)
		{
			// we are not waiting for a end measure
			System.err.println("class Measurement, method end, wrong state");
			return WRONG_STATE;
		}

		long start_time = ((Long) measures.lastElement()).longValue();
		measures.setElementAt(new Long(time - start_time), measures.size() - 1);
		state = false;
		return OK;
	}
	

	/** this method will record a end time for the specified measurement_id
		
	*/
	public int to_stream(PrintWriter pw)
	{
		if (state)
		{
			// we are still waiting for an end measure
			System.err.println("class Measurement, method to_stream, wrong state");
			return WRONG_STATE;
		}

		// all the measures have been finished, dump them to the stream

		// first the header
		pw.println("measurement description: " + description);
		pw.println("times		duration (ms)");

		// dump all the values, caculate max, min and average at the same time
		long min = Long.MAX_VALUE, max = Long.MIN_VALUE, avg = 0;
		long duration = 0;
		int i;

		for (i = 0; i < measures.size(); i++)
		{

			duration = ((Long) measures.elementAt(i)).longValue();
			pw.println(Integer.toString(i + 1) + "	" + Long.toString(duration));

			avg += duration;
			if (duration > max)
			{
				max = duration;
			}
			if (duration < min)
			{
				min = duration;
			}
		}

		if (i == 0)
		{
			// not measure has been done so far
			pw.println("not measure has been performed");
			return OK;
		}

		// at least one measure has been performed
		avg /= i;

		// now dump the statistics
		pw.println("");
		pw.println("max value = " + Long.toString(max) + ", min value = " + 
			Long.toString(min) + ", average = " + Long.toString(avg));

		return OK;
	}
}