package ij.plugin;
import java.awt.*;
import ij.*;

/**ImageJ plugin for measuring the speed of various Java operations.*/
public class Timer implements PlugIn {
	int j=0;
	long startTime, nullLoopTime;
	int numLoops;


	public void run(String arg) {
		int j=0, k;
		int[] a = new int[10];
		long endTime;

		/*
		startTime = System.currentTimeMillis();
		//for (int i=0; i<100; i++) IJ.wait(10);
		for (int i=0; i<100; i++) Thread.yield();
		long elapsedTime = System.currentTimeMillis() - startTime;
		IJ.write(elapsedTime + " ms");
		*/
                
		numLoops = 10000;
		do {
			numLoops = (int)(numLoops*1.33);
			startTime = System.currentTimeMillis();
			for (int i=0; i<numLoops; i++) {}
			nullLoopTime = System.currentTimeMillis() - startTime;
			//IJ.write("loops=" + numLoops + ",  nullLoopTime=" + nullLoopTime);
		} while (nullLoopTime<250);

		IJ.write("");
		IJ.write("Timer: " + numLoops + " iterations (" + nullLoopTime + "ms)");
		Timer2 o = new Timer2();

		// null loop
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {}
		showTime("null loop");

		// i = o.getJ()
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {k = o.getJ();}
		showTime("i=o.getJ()");

		// i = o.getJFinal()
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {k = o.getJFinal();}
		showTime("i=o.getJ() (final)");

		// i = o.getJClass()
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {k = o.getJClass();}
		showTime("i=o.getJ() (static)");

		// i=o.j
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {k = o.j;}
		showTime("i=o.j");

		// i=o.jStatic
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {k = Timer2.k;}
		showTime("i=o.j (static)");

		// i=j
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {k = j;}
		showTime("i=j");

		// i=a[j]
		startTime = System.currentTimeMillis();
		for (int i=0; i<numLoops; i++) {k = a[j];}
		showTime("i=a[j]");

		/*
		long startTime = System.currentTimeMillis();
		for (int i=0; i<=numLoops; i++) {
			IJ.wait(51);
			if (i%50 == 0 )
			IJ.showProgress(i/(double)numLoops);
		}
		long endTime = System.currentTimeMillis();
		IJ.write("  showProgress(): " + (endTime - startTime) + "msecs");

		startTime = System.currentTimeMillis();
		for (int i=0; i<=numLoops; i++) {
			long time = System.currentTimeMillis();
		}
		endTime = System.currentTimeMillis();
		IJ.write("  System.currentTimeMillis(): " + (endTime - startTime) + "msecs");
		*/
	}


	void showTime(String s) {
		long elapsedTime = System.currentTimeMillis() - startTime - nullLoopTime;
		IJ.write("  " + s + ": " + (elapsedTime*1000000)/numLoops + " ns");
	}
	
	
	/*
	void test() {
		//IJ.showMessage("Available for testing");
		//timer();
		//barTest();

		new Main();
	}

	void memoryTest() {
		int i=0;
		MemTest foo=null;
		try {
			while (true) {
				foo=new MemTest(foo,100000);
				i++;
			}
		} catch (OutOfMemoryError e) {
			IJ.log("out of memory at "+i);
		}
	}
	*/

}


	class Timer2 {
		int j=0;
		static int k=0;

		public int getJ() {return j;}
		public final int getJFinal() {return j;}
		public static int getJClass() {return k;}
	}


/*
class MemTest{
	MemTest last; //to keep last one from being garbage collected
	byte[] buf;

	public MemTest(MemTest last, int size) {
		this.last=last;
		buf=new byte[size];
	}
}


class Main extends Frame {
    Main() {
        super("Dialog Example");
        add("West", new Button("Modal"));
        add("East", new Button("Modeless"));
        pack();
        show();
    }
    
    public boolean action(Event evt, Object what) {
        if ("Modal".equals(what)) {
            new MainDialog(this, true);
            return true;
        } else if ("Modeless".equals(what)) {
            new MainDialog(this, false);
            return true;
        }
        return false;
    }

    static public void main(String[] args) {
        new Main();
    }
}


class MainDialog extends Dialog {
    // These two integers hold the location of the last window.
    // New windows are created at an offset to the previous one.
    static int offsetX, offsetY;

    MainDialog(Frame frame, boolean modal) {
        super(frame, modal);
        setTitle(isModal() ? "Modal" : "Modeless");
        add("Center", new Button("Quit"));
        offsetX += 20;
        offsetY += 20;
        setLocation(offsetX, offsetY);
        pack();
        show();
    }

    public boolean action(Event evt, Object what) {
        if ("Quit".equals(what)) {
            dispose();
            return true;
        }
        return false;
    }
}
*/


