package com.koushikdutta.javatests;

import java.lang.Thread;
import java.util.GregorianCalendar;

import sun.misc.GC;

class FibContainer
{
	private int mValue;

	public int getValue()
	{
		return mValue;
	}

	public void setValue(int value)
	{
		mValue = value;
	}

	public void Compute(FibContainer previous, FibContainer beforePrevious)
	{
		setValue(previous.getValue() + beforePrevious.getValue());
	}
}

public class JavaTests
{
	public static void classTest()
	{
		Runtime runtime = Runtime.getRuntime();
		long totalMem = 0;
		long calcTime = 0;
		long allocTime = 0;
		for (int testPass = 0; testPass < 50; testPass++)
		{
			System.gc();

			long memStart = runtime.totalMemory() - runtime.freeMemory();

			long allocStart = System.currentTimeMillis();
			FibContainer[] sequence = new FibContainer[10000];
			for (int i = 0; i < sequence.length; i++)
				sequence[i] = new FibContainer();
			long allocEnd = System.currentTimeMillis();

			long memEnd = runtime.totalMemory() - runtime.freeMemory();

			sequence[0].setValue(1);
			sequence[1].setValue(1);
			long calcStart = System.currentTimeMillis();
			for (int i = 2; i < sequence.length; i++)
				sequence[i].Compute(sequence[i - 1], sequence[i - 2]);
			long calcEnd = System.currentTimeMillis();

			System.out.println("The last Fibonacci number is " + sequence[sequence.length - 1].getValue());

            if (testPass == 0)
				continue;

			totalMem += (memEnd - memStart);
			calcTime += (calcEnd - calcStart);
			allocTime += (allocEnd - allocStart);
		}

		System.out.println("Memory: " + totalMem);
		System.out.println("Allocation: " + allocTime);
		System.out.println("Calculation: " + calcTime);
	}

	public static void selectionSortTest()
	{
		// total time for the tests
		long totalTime = 0;
		// allocate once
		int[] numbers = new int[1000];

		for (int testPass = 0; testPass < 10; testPass++)
		{
			// reset to decreasing order
			for (int i = 0; i < numbers.length; i++)
			{
				numbers[i] = numbers.length - i;
			}

			// note the start time
			long start = System.currentTimeMillis();
			// sort to increasing order
			for (int i = 0; i < numbers.length; i++)
			{
				int min = numbers[i];
				int minIndex = i;
				for (int j = i + 1; j < numbers.length; j++)
				{
					int thisVal = numbers[j];
					if (numbers[j] < min)
					{
						min = thisVal;
						minIndex = j;
					}
				}
				numbers[minIndex] = numbers[i];
				numbers[i] = min;
			}
			// note the end time
			long end = System.currentTimeMillis();

			long elapsed = end - start;

			System.out.println("The smallest number is " + numbers[0]);

            // don't tally the first pass- I'm not sure how the Mono/Dalvik caching and JIT works, but, I'll
			// just assume that the first pass over a method will probably incur some one time overhead costs.
			if (testPass == 0)
				continue;

			totalTime += elapsed;
		}

		System.out.println("Time: " + totalTime);
	}

	public static void showHelp()
	{
		System.out.println("Selection Sort: ss");
		System.out.println("Class Test: ct");
	}

	public static void main(String[] args)
	{
		if (args.length != 1)
			showHelp();
		else if (args[0].equals("ss"))
			selectionSortTest();
		else if (args[0].equals("ct"))
			classTest();
		else
			showHelp();
	}
}