#include <catch2/catch.hpp>
#include <memory>
#include <alib/vector>
#include <libgen.h>
#include <map>

#include "testing/TimeoutAqlTest.hpp"
#include "testing/TestFiles.hpp"

#include "glushkovRteTestGenerators.hpp"

static size_t TESTCASES = 50;

std::map < std::string, std::shared_ptr < TreeGenerator > > m_Generators = {
	{ "rte0.xml", std::make_shared < TreeGenerator0 > ( ) },
	{ "rte1.xml", std::make_shared < TreeGenerator1 > ( ) },
	{ "rte2.xml", std::make_shared < TreeGenerator2 > ( ) },
	{ "rte3.xml", std::make_shared < TreeGenerator3 > ( ) },
	{ "rte4.xml", std::make_shared < TreeGenerator4 > ( ) },
	{ "rte5.xml", std::make_shared < TreeGenerator5 > ( ) },
	{ "rte6.xml", std::make_shared < TreeGenerator6 > ( ) },
	{ "rte7.xml", std::make_shared < TreeGenerator7 > ( ) },
	{ "rte8.xml", std::make_shared < TreeGenerator8 > ( ) },
	{ "rte9.xml", std::make_shared < TreeGenerator9 > ( ) },
};

TEST_CASE ( "GlushkovRTE", "[integration]" ) {

	SECTION ( "To PDA" ) {
		for ( const std::string & file : TestFiles::Get ( "/rte/rte[0-9]+.xml$" ) ) {
			char * p_filepath = strdup ( file.c_str ( ) );
			std::string base = basename ( p_filepath ); // be careful, there are posix and gnu versions
			free ( p_filepath );

			try {
				for ( size_t i = 0; i < TESTCASES; i++ ) {
					ext::vector < std::string > qs = {
						"execute < " + file + " | rte::convert::ToPostfixPushdownAutomatonGlushkov - | automaton::determinize::Determinize - > $pda",
						"execute \"" + m_Generators.at ( base ) -> generate ( ) + "\" | Move - | string::Parse @tree::Tree - | "
							"string::transform::StringConcatenate ( PostfixRankedTree ) - <(string::Parse @string::String \"\\\"#$\\\"\") > $string",
						"quit automaton::run::Accept $pda $string",
					};

					TimeoutAqlTest ( 5s, qs );
				}
			} catch ( const std::out_of_range & ) {
				FAIL ( "No generator assigned for file " << file );
			}
		}
	}

	SECTION ( "To FTA" ) {
		for ( const std::string & file : TestFiles::Get ( "/rte/rte[0-9]+.xml$" ) ) {
			char * p_filepath = strdup ( file.c_str ( ) );
			std::string base = basename ( p_filepath ); // be careful, there are posix and gnu versions
			free ( p_filepath );

			try {
				for ( size_t i = 0; i < TESTCASES; i++ ) {
					ext::vector < std::string > qs = {
						"execute < " + file + " | rte::convert::ToFTAGlushkov - | automaton::determinize::Determinize - > $fta",
						"execute \"" + m_Generators.at ( base ) -> generate ( ) + "\" | Move - | string::Parse @tree::Tree - > $input",
						"quit automaton::run::Accept $fta (PostfixRankedTree)$input",
					};

					TimeoutAqlTest ( 5s, qs );
				}
			} catch ( const std::out_of_range & ) {
				FAIL ( "No generator assigned for file " << file );
			}
		}
	}
}
