package org.adg.learning.algorithm.sorting.test;

import java.util.Arrays;

import org.adg.learning.algorithm.sorting.SelectionSort;
import org.adg.learning.util.Comparators;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestSelectionSort {

	private static final Logger logger = LoggerFactory.getLogger(TestSelectionSort.class);

	private static final Integer[] INTARRAY_0ELE = new Integer[] {};
	private static final Integer[] INTARRAY_1ELE = new Integer[] { 0 };
	private static final Integer[] INTARRAY_2ELES_SORTED = new Integer[] { 0, 1 };
	private static final Integer[] INTARRAY_SORTED = new Integer[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

	@Test
	public void sort_0ele() {
		Integer[] toSorted = new Integer[] {};
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_0ELE, toSorted);
	}

	@Test
	public void sort_1ele() {
		Integer[] toSorted = new Integer[] { 0 };
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_1ELE, toSorted);
	}

	@Test
	public void sort_2eles() {
		Integer[] toSorted = new Integer[] { 1, 0 };
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_2ELES_SORTED, toSorted);
	}

	@Test
	public void sort_already_sorted() {
		Integer[] toSorted = new Integer[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_SORTED, toSorted);
	}

	@Test
	public void sort1() {
		Integer[] toSorted = new Integer[] { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9 };
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_SORTED, toSorted);
	}

	@Test
	public void sort2() {
		Integer[] toSorted = new Integer[] { 2, 1, 0, 3, 4, 5, 6, 7, 8, 9 };
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_SORTED, toSorted);
	}

	@Test
	public void sort3() {
		Integer[] toSorted = new Integer[] { 3, 1, 2, 0, 4, 5, 6, 7, 8, 9 };
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_SORTED, toSorted);
	}

	@Test
	public void sort_reversed_array() {
		Integer[] toSorted = new Integer[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(INTARRAY_SORTED, toSorted);
	}

	private void sort_random() {
		int len = 10000;
		Integer[] toSorted = new Integer[len];
		for (int i = 0; i < len; i++) {
			toSorted[i] = (int) Math.round(Math.random() * len);
		}

		// logger.info("Array to be sorted: {}", Arrays.toString(toSorted));
		// copy and sort by JDK
		Integer[] sortedByJava = Arrays.copyOf(toSorted, toSorted.length);
		Arrays.sort(sortedByJava, Comparators.COMPARATOR_INTEGER);

		SelectionSort.sort(toSorted, Comparators.COMPARATOR_INTEGER);

		Assert.assertArrayEquals(sortedByJava, toSorted);
		// logger.info("Array sorted OK: {}\n\n", Arrays.toString(toSorted));
	}

	@Test
	public void multi_random_sort() {
		for (int i = 0; i < 10; i++) {
			sort_random();
		}
	}

}
