/*
 * FMIndexFactorsTest.cpp.c
 *
 *  Created on: 27. 02. 2021
 *      Author: Martin Prokopic
 */

#include <catch2/catch.hpp>

#include <string/String.h>
#include <stringology/transform/BWTNaive.h>
#include <stringology/indexing/BWTAuxiliaryDataConstruct.h>
#include <stringology/indexing/SimpleFMIndexConstruct.h>
#include <stringology/query/FMIndexFactors.h>

using stringology::transform::BWTNaive;
using stringology::indexing::BWTAuxiliaryDataConstruct;
using stringology::indexing::SimpleFMIndexConstruct;
using stringology::query::FMIndexFactors;
using string::LinearStringTerminatingSymbolBWT;

TEST_CASE ( "FM Index Factors", "[unit][stringology][query][fmindex][bwt]" ) {

    SECTION ( "basic test" ) {
        auto testcase = GENERATE (
                std::make_tuple ( "banana", "na", ext::set < unsigned >{ 2, 4 } ),
                std::make_tuple ( "banana", "ana", ext::set < unsigned >{ 1, 3 } ),
                std::make_tuple ( "banana", "ba", ext::set < unsigned >{ 0 } ),
                std::make_tuple ( "banana", "z", ext::set < unsigned > ( )),
                std::make_tuple ( "banana", "asdf", ext::set < unsigned > ( )),
                std::make_tuple ( "", "asdf", ext::set < unsigned > ( )));

        auto originalSubject = string::stringFrom ( std::get < 0 > ( testcase ));
        auto pattern = string::stringFrom ( std::get < 1 > ( testcase ));

        auto transformedSubject = stringology::transform::BWTNaive::construct ( originalSubject );

        auto data = BWTAuxiliaryDataConstruct::construct ( transformedSubject );
        INFO ( data );

        auto index = SimpleFMIndexConstruct::construct ( transformedSubject, 4, 2, 2 );
        auto matches = FMIndexFactors::match ( index, pattern );
        REQUIRE ( matches == std::get < 2 > ( testcase ));
    }

    SECTION ( "throws exception if pattern is empty" ) {
        auto subject = LinearStringTerminatingSymbolBWT < char > ( '$', string::stringFrom ( "subject$" ));
        auto pattern = string::stringFrom ( "" );

        auto index = SimpleFMIndexConstruct::construct ( subject, 4, 2, 2 );
        REQUIRE_THROWS_AS( FMIndexFactors::match ( index, pattern ), exception::CommonException );
    }

    SECTION ( "checks if index is fat (fttDensityPct > 0)" ) {
        auto subject = LinearStringTerminatingSymbolBWT < char > ( '$', string::stringFrom ( "subject$" ));
        auto pattern = string::stringFrom ( "sub" );

        auto index = SimpleFMIndexConstruct::construct ( subject, 4, 2, 0 );
        REQUIRE_THROWS_AS( FMIndexFactors::match ( index, pattern ), exception::CommonException );
    }
}