#include <UnitTest++.h>

#include "Logging.h"
#include "Commands.h"
#include "CommandsGlobal.h"

using namespace std;
using namespace Engine;

int global_int = -1;
string global_string = "";
vector<string> global_values;

struct CommandsFixture {
	CommandsFixture () {
		LoggingModule.Init (0, NULL);
		LoggingModule.SetLogPrintLevel (LogLevelWarning);
		CommandsModule.Init (0, NULL);
	}

	~CommandsFixture () {
		CommandsModule.Destroy ();
		LoggingModule.Destroy ();
	}

	Logging LoggingModule;
	Commands CommandsModule;
};

bool test_cmd_set_global_int (vector<string> argv) {
	global_int = 1;
	return true;
};

bool test_cmd_set_global_string (vector<string> argv) {
	if (argv.size() > 0) {
		global_string = argv[0];
		return true;
	}

	return false;
}

bool test_cmd_set_global_values (vector<string> argv) {
	global_values = argv;
	return true;
};

bool test_cmd_set_error (vector<string> argv) {
	if (argv.size() > 0) {
		CommandSetErrorString ("too many arguments passed to function!");
		return false;
	}

	return true;
}

TEST_FIXTURE ( CommandsFixture, CommandSystemAddCommand ) {
	AddCommand ("test", test_cmd_set_global_int);
	CHECK_EQUAL (true, RunCommand ("test"));
}

TEST_FIXTURE ( CommandsFixture, CommandSystemRun ) {
	global_int = -1;

	AddCommand ("test", test_cmd_set_global_int);
	CHECK_EQUAL (true, RunCommand ("test"));

	CHECK_EQUAL (1, global_int);
}

TEST_FIXTURE ( CommandsFixture, CommandSystemArgv ) {
	global_string = "oldstring";
	AddCommand ("test_string", test_cmd_set_global_string);
	CHECK_EQUAL (1, RunCommand ("test_string newstring"));

	CHECK_EQUAL ("newstring", global_string);
}

TEST_FIXTURE ( CommandsFixture, CommandSystemArgValues ) {
	global_values.clear();
	AddCommand ("test_values", test_cmd_set_global_values);
	CHECK_EQUAL (true, RunCommand ("test_values   value1 value2  value3 "));

	CHECK_EQUAL (static_cast<unsigned int> (3), global_values.size());
	if (global_values.size() == 3) {
		CHECK_EQUAL ("value1", global_values[0]);
		CHECK_EQUAL ("value2", global_values[1]);
		CHECK_EQUAL ("value3", global_values[2]);
	}

	global_values.clear ();
	CHECK_EQUAL (true, RunCommand ("test_values"));
	CHECK_EQUAL (static_cast<unsigned int> (0), global_values.size());
	
	global_values.clear ();
	CHECK_EQUAL (true, RunCommand ("test_values value1 \"value consisting of a string\""));
	CHECK_EQUAL (static_cast<unsigned int> (2), global_values.size());

	if (global_values.size () == 2) {
		CHECK_EQUAL ("value consisting of a string", global_values[1]);
	}

	global_values.clear ();
	CHECK_EQUAL (true, RunCommand ("test_values \"value consisting of a string\""));
	CHECK_EQUAL (static_cast<unsigned int> (1), global_values.size());

	if (global_values.size () == 1) {
		CHECK_EQUAL ("value consisting of a string", global_values[0]);
	}
}

TEST_FIXTURE ( CommandsFixture, CommandSystemQueue ) {
	global_string = "oldstring";
	global_int = -1;

	AddCommand ("test_string", test_cmd_set_global_string);
	AddCommand ("test_int", test_cmd_set_global_int);

	QueueCommand ("test_string newstring");
	QueueCommand ("test_int");
	CommandQueueExecute ();

	CHECK_EQUAL ("newstring", global_string);
	CHECK_EQUAL (1, global_int);
}

TEST_FIXTURE ( CommandsFixture, CommandSystemError ) {
	AddCommand ("set_error", test_cmd_set_error);

	CHECK_EQUAL (false, RunCommand ("set_error error"));
	CHECK_EQUAL ("too many arguments passed to function!", CommandGetErrorString ());

	CHECK_EQUAL (true, RunCommand ("set_error"));
	CHECK_EQUAL ("", CommandGetErrorString ());
}


