/*
 * BWTFromSuffixArrayNaive.h
 *
 *  Created on: 13. 02. 2021
 *      Author: Martin Prokopic
 */

#pragma once

#include <indexes/stringology/SuffixArray.h>
#include <string/LinearStringTerminatingSymbolBWT.h>
#include <alphabet/MinimalEndSymbol.h>

namespace stringology {

namespace transform {

class BWTFromSuffixArrayNaive {
public:
    /**
     * Construct BWT-encoded string from a suffix array of a string without terminating symbol. The terminating symbol is appended during construction.
     *
     * @tparam SymbolType
     * @param sa the suffix array
     * @return the BWT-encoded string
     */
    template < class SymbolType >
    static string::LinearStringTerminatingSymbolBWT < SymbolType >
    construct ( const indexes::stringology::SuffixArray < SymbolType > & sa );
};

template < class SymbolType >
string::LinearStringTerminatingSymbolBWT < SymbolType >
BWTFromSuffixArrayNaive::construct ( const indexes::stringology::SuffixArray < SymbolType > & sa ) {
    const auto & originalString = sa.getString ( );
    const SymbolType terminatingSymbol = alphabet::MinimalEndSymbol::instance < SymbolType > ( );

    if ( originalString.size ( ) == 0 )
        return string::LinearStringTerminatingSymbolBWT < SymbolType > (
                sa.getAlphabet ( ) + ext::set < SymbolType >{ terminatingSymbol },
                terminatingSymbol,
                ext::vector < SymbolType >{ terminatingSymbol } );

    ext::vector < SymbolType > bwtData;
    bwtData.push_back ( originalString.getContent ( )[ originalString.size ( ) - 1 ] ); // "$" would be first suffix
    for ( size_t i = 0; i < originalString.size ( ); i ++ ) {
        if ( sa.getData ( )[ i ] == 0 )
            bwtData.push_back ( terminatingSymbol );
        else
            bwtData.push_back ( originalString.getContent ( )[ sa.getData ( )[ i ] - 1 ] );
    }

    return string::LinearStringTerminatingSymbolBWT < SymbolType > (
            sa.getAlphabet ( ) + ext::set < SymbolType >{ terminatingSymbol },
            terminatingSymbol, bwtData );
}

} /* namespace transform */

} /* namespace stringology */
