/*
 * TestParser.cpp
 *
 *  Created on: Dec 22, 2012
 *      Author: att
 */

#include "TestParser.h"

TestParser::TestParser() {


}

TestParser::~TestParser() {

}

std::string TestParser::test_parsing_and_evaluating_logical_expressions()
{
	std::string test_report = "";
	std::vector<InputOutputPair> logical_inputs = prepare_logical_input();
	Lexer lexer;
	ContextManager context;
	Parser parser(&context);
	for(auto logical_case : logical_inputs)
	{
		auto tokens = lexer.parse_line(logical_case.first);
		parser.add_tokens(tokens);
		parser.interpret();
		SenchaObject value = parser.program->evaluate_last();
		parser.erase_all();
		muu_assert("Logical value isn't correct", value.truthy == logical_case.second);
	}
	return test_report;
}

std::string TestParser::test_adding_new_function()
{
	std::string test_report = "";
	std::string function_declaration = "def print_hello(how_many_times) {";
	function_declaration += " repeat(how_many_times) { print(\"Hello\");}";

	ContextManager context;
	Parser parser(&context);
	Lexer lexer;
	auto tokens = lexer.parse_line(function_declaration);
	parser.add_tokens(tokens);
	parser.interpret();

	return test_report;
}

std::string TestParser::test_calling_funtion()
{
	std::string test_report = "";
	Lexer lexer;
	ContextManager context;
	Parser parser(&context);
	std::string call = " max(77, 12);";
	auto tokens = lexer.parse_line(prepare_some_function_declarations() + call);
	parser.add_tokens(tokens);
	parser.interpret();
	auto value =  parser.program->execute_last();
	muu_assert("function max doesn't work", value.integer == 77);
	std::cout << "function call returned " << value.repr() << std::endl;
	return test_report;
}

std::string TestParser::prepare_some_function_declarations()
{
	/*std::string print_hello_declaration ="def print_hello(how_many_times) {";
	print_hello_declaration += " repeat(how_many_times) { print(\"Hello\");}";

	std::string how_long_declaration = "def how_long(some_text) {";
	how_long_declaration += " return len(some_text);}";


	std::string max_declaration = "def max(a, b) { ";
	max_declaration += "if(a > b) return a;";
	max_declaration += "else return b; }";

	std::string min_declaration = "def min(a, b) { ";
	min_declaration += "if(a < b) return a;";
	min_declaration += "else return b; }";

	std::string multiply_string_declaration = "def multiply_string(text, i) {";
	multiply_string_declaration += "result = \"\"; ";
	multiply_string_declaration += "repeats(i) { result = result + text }";
	multiply_string_declaration += " return result; ";*/

	std::string max_declaration = "def max(a, b) { ";
		max_declaration += "if(a > b) return a; ";
		max_declaration += "else return b; }";

	return max_declaration;
}

std::vector<TestParser::SInputOutputPair> TestParser::prepare_function_call_input()
{
	std::vector<SInputOutputPair> function_calls;

	function_calls.push_back(SInputOutputPair("print_hello(77);", SenchaObject()));
	function_calls.push_back(SInputOutputPair("how_long(\"elephant\");", SenchaObject(8)));
	function_calls.push_back(SInputOutputPair("max(77, 12);", SenchaObject(77)));
	function_calls.push_back(SInputOutputPair("min(12, 1);", SenchaObject(1)));
	function_calls.push_back(SInputOutputPair("multiply_string(\"alfa\", 3);", SenchaObject("alfaalfaalfa")));

	return function_calls;

}

std::vector<TestParser::InputOutputPair> TestParser::prepare_logical_input()
{
	std::vector<InputOutputPair> logical_inputs;
	logical_inputs.push_back(InputOutputPair("false and false", false));
	logical_inputs.push_back(InputOutputPair("false and true", false));
	logical_inputs.push_back(InputOutputPair("true and false", false));
	logical_inputs.push_back(InputOutputPair("true and true", true));
	logical_inputs.push_back(InputOutputPair("false or false", false));
	logical_inputs.push_back(InputOutputPair("false or true", true));
	logical_inputs.push_back(InputOutputPair("true or false", true));
	logical_inputs.push_back(InputOutputPair("true or true", true));
	logical_inputs.push_back(InputOutputPair("(true or false) and (true or false)", true));
	logical_inputs.push_back(InputOutputPair("7 + 2 > 55 or 6-5 == 1", true));

	return logical_inputs;
}


std::string TestParser::all_tests()
{
	std::string test_report = "";

	mu_run_test(test_parsing_and_evaluating_logical_expressions);
	mu_run_test(test_calling_funtion);

	return test_report;
}

/*TODO
 * write test of evaluating logical expression
 * possible input:
 *
 * some variable == "g" and other != "a"
 *
 * some easy expression like:
 *  if("aaa" != "bbb" and 2 < 5) {
>>     print(1);
>>     } else {
>>     print(0);
>>     }
 */
