#include "Test.h"
#include "TestReporterStdout.h"
#include "UnitTest++.h"
#include "bdmerror.h"
#include "itpp_ext.h"
#include <string.h>

using std::cout;
using std::cerr;
using std::endl;

using namespace itpp;

Array<const char *> selected_tests;

bool is_selected_test ( const UnitTest::Test *test ) {
	bdm_assert_debug ( test, "NULL test" );

	if ( !selected_tests.length() ) {
		return true;
	}

	for ( int i = 0; i < selected_tests.length(); ++i ) {
		const char *n = test->m_details.testName;
		bdm_assert_debug ( n, "NULL test name" );
		const char *sname = selected_tests ( i );
		bdm_assert_debug ( sname, "NULL selected test name" );
		if ( !strcmp ( n, sname ) ) {
			return true;
		}
	}

	return false;
}

int main ( int argc, char const *argv[] ) {
	if ( argc > 1 ) {
		if ( !strcmp ( argv[1], "print" ) ) {
			UnitTest::Test* curTest = UnitTest::Test::GetTestList().GetHead();

			while ( curTest != 0 ) {
				const char *n = curTest->m_details.testName;
				printf ( "%s\n", n );
				curTest = curTest->next;
			}
			return 0;
		} else {
			selected_tests.set_length ( argc - 1 );
			const char **param = argv + 1;
			int i = 0;
			while ( *param ) {
				selected_tests ( i ) = *param;
				++i;
				++param;
			}
		}
	} else {
		cout << "usage: " << endl <<
		     "\"" << argv[0] << "\" - to run all unit tests " << endl <<
		     "\"" << argv[0] << " particular_test_1 particular_test_2\" - to run selected unit tests" << endl <<
		     "\"" << argv[0] << " print\" - to print all the implemented unit tests" << endl;
	}

	itpp::RNG_randomize();

	UnitTest::TestReporterStdout reporter;
	UnitTest::TestRunner runner ( reporter );
	return runner.RunTestsIf ( UnitTest::Test::GetTestList(),
	                           0,
	                           is_selected_test,
	                           0 );
}
