#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#include <boost/chrono.hpp>

#include "sort_algorithms.hpp"
#include "row.hpp"

void fill_random(double* arr, int n)
{
	for (int i=0; i<n; i++)
		arr[i] = ((double)rand()/RAND_MAX) * 20000.0 - 10000.0
}

bool is_sorted(row<double>& r)
{
	for (uint32_t i=1; i<r.size();i++)
		if (r[i]<r[i-1]) return false;
	return true;
}

template<typename SortFn>
long long time_sort(double* src, int n, SortFn fn, bool& correct)
{
	row<double>* a = new row<double>(src, n);

	boost::chrono::high_resolution_clock::time_point start =
	boost::chrono::high_resolution_clock::now();

	fn(*a);

	boost::chrono::high_resolution_clock::time_point stop =
	boost::chrono::high_resolution_clock::now();

	correct = is_sorted(*a);
	delete a;

	return std::chrono::duration_cast<boost::chrono::microseconds>(stop-start).count();
}


int main()
{
	srand(42);

	const int sizes[2] = {1000, 10000};

	struct Entry {
		std::string name;
		int        n;
		long long  us;
		bool       ok;
	}

	Entry results[12];
	int idx = 0;

	for (int si=0; si<2; si++)
	{
		int n = sizes[si];
		double* src = new double[n];
		fill_random(src, n);

		auto run = [&](const std::string& name, auto fn) {
			bool ok;
			long long t = time_sort(src, n, fn, ok);
			results[idx++] = {name, n, t, ok};

		run("Bubble",      [](row<double>& r){ bubble_sort(r);      });
		run("Selection",   [](row<double>& r){ selection_sort(r);   });
		run("Insertion",   [](row<double>& r){ insertion_sort(r);   });
		run("Merge",       [](row<double>& r){ merge_sort(r);       });
		run("Quick",       [](row<double>& r){ quick_sort(r);       });
		run("Enumeration", [](row<double>& r){ enumeration_sort(r); });

		delete[] src;
	}

	std::cout << "\n";
	std::cout << std::string(60, '=') << "\n";
	std::cout << "  Sorting Algorithm Test Report\n";
	std::cout << "  Input: random doubles in [-10000, 10000]\n";
	std::cout << std::string(60, '=') << "\n\n";

	std::cout << std::left
                  << std::setw(14) << "Algorithm"
                  << std::setw(10) << "n"
                  << std::setw(14) << "Time (us)"
                  << std::setw(10) << "Correct"
                  << "\n";

        std::cout << std::string(48, '-') << "\n";

	        for (int i = 0; i < idx; i++) {
	        

	return 0;
}


