package basicExamples;
import java.util.Arrays;
import java.util.Random;

public class SortWithThreadsDemo {
	
	public static void main(String[] args) {
		SortWithThreadsDemo sd = new SortWithThreadsDemo();
		Random rand = new Random(System.currentTimeMillis());
		int n = 50000; // 50000 takes 5-10 seconds.
		//int n = 30; // 30 is good to demonstrate correctness (or not).
		int[] a = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = rand.nextInt(10 * n);
		}
		sd.printArray(a);
		
		//---------------------------------------------------
		// Sort with the parallel algorithm
		int []b = Arrays.copyOf(a, a.length);
		long start = System.currentTimeMillis();
		//sd.sortParallel(b);
		sd.sortParallelVersion1(b);
		long end = System.currentTimeMillis();
		System.out.println("Total time parallel: "+(end-start));
		sd.printArray(b);		

		//---------------------------------------------------
		// Sort with the serial algorithm
		b = Arrays.copyOf(a, a.length);
		start = System.currentTimeMillis();
		sd.sortSerial(b);
		end = System.currentTimeMillis();
		System.out.println("Total time serial: "+(end-start));
		sd.printArray(b);
		
		//---------------------------------------------------
		// Sort with the serial algorithm--just Bubble
		b = Arrays.copyOf(a, a.length);
		start = System.currentTimeMillis();
		sd.sortSerialWithJustBubble(b);
		end = System.currentTimeMillis();
		System.out.println("Total time serial (just bubble): "+(end-start));
		sd.printArray(b);
	}
	public void sortParallelVersion1(int[] a) {
		int l = 0;
		int r = a.length - 1;
		int m = a.length / 2 - 1;

		SortThread st1 = new SortThread(a, l, m);
		SortThread st2 = new SortThread(a, m + 1, r);
		st1.start();
		st2.start();
		merge(a, l, m, r);
	}
	public void sortSerialWithJustBubble(int[] a) {
		SortThread st1 = new SortThread(a, 0,a.length-1);
		st1.start();		
		try {
			st1.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public void sortSerial(int[] a) {
		int l = 0;
		int r = a.length - 1;
		int m = a.length / 2 - 1;

		SortThread st1 = new SortThread(a, l, m);
		SortThread st2 = new SortThread(a, m + 1, r);
		st1.run();
		st2.run();
		merge(a, l, m, r);
	}
	public void sortParallel(int[] a) {
		int l = 0;
		int r = a.length - 1;
		int m = a.length / 2 - 1;

		SortThread st1 = new SortThread(a, l, m);
		SortThread st2 = new SortThread(a, m + 1, r);
		st1.start();
		st2.start();
		try {
			st1.join();
			st2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		merge(a, l, m, r);
	}

	public void merge(int A[], int L, int m, int R) {
		int size = R - L + 1;
		int mid = m - L + 1;
		int[] B = new int[size];
		for (int i = 0; i < mid; i++)
			B[i] = A[L + i];
		for (int j = mid; j < size; j++)
			B[j] = A[R - j + mid];
		int i = 0;
		int j = size - 1;
		for (int k = L; k <= R; k++) {
			if (B[i] < B[j]) {
				A[k] = B[i];
				i++;
			} else {
				A[k] = B[j];
				j--;
			}
		}
	}

	public void printArray(int[] a) {
		for (int i = 0; i < a.length; i++) {
			System.out.print(a[i] + ", ");
		}
		System.out.println("");
	}
}
