#include <catch2/catch.hpp>

#include <string/String.h>
#include <stringology/indexing/ExperimentalCompactSuffixAutomatonConstruct.h>
#include <stringology/query/CompactSuffixAutomatonFactors.h>
#include <stringology/exact/ExactFactorMatch.h>

#include <string/generate/RandomStringFactory.h>
#include <string/generate/RandomSubstringFactory.h>

TEST_CASE ( "CDAWG", "[unit][stringology]" ) {
	ext::vector<std::string> subjects;
	ext::vector<std::string> patterns;

	subjects.push_back("a"); patterns.push_back("a");
	subjects.push_back("a"); patterns.push_back("b");
	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfa");
	subjects.push_back("alfalfalfa"); patterns.push_back("blfalfalfa");
	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfb");
	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa");
	subjects.push_back("alfalfalfaalfalfalfaabfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa");
	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa");
	subjects.push_back("atggccttgcc"); patterns.push_back("gcc");
	subjects.push_back("aaaaaaaaaa"); patterns.push_back("a");

	for(size_t i = 0; i < subjects.size(); ++i) {
		string::LinearString < > subject = core::normalize < string::LinearString < char > >::eval ( string::LinearString < char > ( subjects[i] ) );
		string::LinearString < > pattern = core::normalize < string::LinearString < char > >::eval ( string::LinearString < char > ( patterns[i] ) );

		indexes::stringology::CompactSuffixAutomatonTerminatingSymbol < > index = stringology::indexing::ExperimentalCompactSuffixAutomatonConstruct::construct ( subject );

		ext::set < unsigned > res = stringology::query::CompactSuffixAutomatonFactors::query ( index, pattern );
		ext::set < unsigned > ref = stringology::exact::ExactFactorMatch::match ( subject, pattern );

		CAPTURE ( subjects [ i ], patterns [ i ], res, ref );
		CHECK ( res == ref );
	}

	auto longSubject = string::generate::RandomStringFactory::generateLinearString ( 4000, 26, false, true );
	auto longPattern = string::generate::RandomSubstringFactory::generateSubstring ( 2, longSubject );

	indexes::stringology::CompactSuffixAutomatonTerminatingSymbol < std::string > index = stringology::indexing::ExperimentalCompactSuffixAutomatonConstruct::construct ( longSubject );

	ext::set < unsigned > res = stringology::query::CompactSuffixAutomatonFactors::query ( index, longPattern );
	ext::set < unsigned > ref = stringology::exact::ExactFactorMatch::match ( longSubject, longPattern );

	CAPTURE ( res, ref );
	CHECK ( res == ref ) ;
}
