//
// Created by hruskraj on 4. 5. 2020
//

#include <catch2/catch.hpp>

#include <alib/set>
#include <string/LinearString.h>
#include <stringology/cover/RelaxedApproximateEnhancedCoversComputation.h>

TEST_CASE ( "Relaxed Approximate Enhanced Covers", "[unit][stringology][cover]" ) {
	SECTION ( "Basic test" ) {
		string::LinearString < char > pattern;
		unsigned int k;
		ext::set < string::LinearString < char > > refSet;

		SECTION ( "One simple enhanced cover" ) {
			pattern = string::LinearString < char > ( "abcabc" );
			k = 1;
			refSet = { string::LinearString < char > ( "abc" ) };

		}

		SECTION ( "Multiple relaxed approximate enhanced covers" ) {
			pattern = string::LinearString < char > ( "abacaccababa" );
			k = 2;

			refSet = {
				string::LinearString < char > ( "cca" ),
				string::LinearString < char > ( "aba" ),
				string::LinearString < char > ( "aca" ),
				string::LinearString < char > ( "acc" ),
				string::LinearString < char > ( "abaca" ),
				string::LinearString < char > ( "ababa" ),
			};

		}
		CHECK ( stringology::cover::RelaxedApproximateEnhancedCoversComputation::compute ( pattern, k ) == refSet );
	}

	SECTION ( "Empty string" ) {
		string::LinearString < char > pattern ( "" );
		unsigned int k = 0;

		SECTION ( "k = 0" ) {
			k = 0;
		}
		SECTION ( "k = 1" ) {
			k = 1;
		}
		SECTION ( "k = 15" ) {
			k = 15;
		}
		SECTION ( "k = -1" ) {
			k = -1;
		}

		CHECK ( stringology::cover::RelaxedApproximateEnhancedCoversComputation::compute ( pattern, k ).empty ( ) );
	}

	SECTION ( "k = 0 (enhanced covers)" ) {
		unsigned int k = 0;
		string::LinearString < char > pattern;
		ext::set < string::LinearString < char > > refSet;

		SECTION ( "pattern x" ) {
			pattern = string::LinearString < char > ( "x" );
			refSet = {};
		}
		SECTION ( "pattern ab" ) {
			pattern = string::LinearString < char > ( "ab" );
			refSet = {};
		}
		SECTION ( "pattern aa" ) {
			pattern = string::LinearString < char > ( "aa" );
			refSet = { string::LinearString < char > ( "a" ) };
		}
		SECTION ( "pattern aba" ) {
			pattern = string::LinearString < char > ( "aba" );
			refSet = { string::LinearString < char > ( "a" ) };
		}
		SECTION ( "pattern aaa" ) {
			pattern = string::LinearString < char > ( "aaa" );
			refSet = { string::LinearString < char > ( "a" ), string::LinearString < char > ( "aa" ) };
		}

		CHECK ( stringology::cover::RelaxedApproximateEnhancedCoversComputation::compute ( pattern, k ) == refSet );
	}

	SECTION ( "Different k" ) {
		string::LinearString < char > pattern ( "abbbabab" );
		unsigned int k;
		ext::set < string::LinearString < char > > refSet;

		SECTION ( "k = 4" ) {
			k = 4;
			refSet = {
				string::LinearString < char > ( "bbaba" ),
				string::LinearString < char > ( "bbbaba" ),
				string::LinearString < char > ( "babab" ),
				string::LinearString < char > ( "bbbab" ),
				string::LinearString < char > ( "abbbab" ),
				string::LinearString < char > ( "abbba" ),
				string::LinearString < char > ( "bbabab" ),
			};
		}

		SECTION ( "k = 3" ) {
			k = 3;
			refSet = {
				string::LinearString < char > ( "abbb" ),
				string::LinearString < char > ( "bbba" ),
				string::LinearString < char > ( "bbab" ),
				string::LinearString < char > ( "bbbab" ),
				string::LinearString < char > ( "abab" ),
				string::LinearString < char > ( "bbabab" ),
				string::LinearString < char > ( "abbbab" )
			};
		}

		CHECK ( stringology::cover::RelaxedApproximateEnhancedCoversComputation::compute ( pattern, k ) == refSet );
	}
}
