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

#pragma once

#include <indexes/stringology/SimpleFMIndex.h>

#include <sax/FromXMLParserHelper.h>
#include <core/xmlApi.hpp>

#include <primitive/xml/Unsigned.h>
#include <container/xml/ObjectsVector.h>
#include <container/xml/ObjectsMap.h>
#include <container/xml/ObjectsSet.h>

#include <string/xml/LinearString.h>
#include <string/xml/LinearStringTerminatingSymbolBWT.h>

namespace core {

template < class SymbolType >
struct xmlApi < indexes::stringology::SimpleFMIndex < SymbolType > > {
    static indexes::stringology::SimpleFMIndex < SymbolType > parse ( ext::deque < sax::Token >::iterator & input );

    static bool first ( const ext::deque < sax::Token >::const_iterator & input );

    static std::string xmlTagName ( );

    static void
    compose ( ext::deque < sax::Token > & output, const indexes::stringology::SimpleFMIndex < SymbolType > & index );
};

template < class SymbolType >
indexes::stringology::SimpleFMIndex < SymbolType >
xmlApi < indexes::stringology::SimpleFMIndex < SymbolType > >::parse (
        ext::deque < sax::Token >::iterator & input ) {
    sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, xmlTagName ( ));

    auto str = core::xmlApi < string::LinearStringTerminatingSymbolBWT < SymbolType > >::parse ( input );

    unsigned superBucketSize = core::xmlApi < unsigned >::parse ( input );
    unsigned bucketSize = core::xmlApi < unsigned >::parse ( input );
    auto superBucketOcc = core::xmlApi < ext::vector < ext::map < SymbolType, unsigned > > >::parse ( input );
    auto bucketOcc = core::xmlApi < ext::vector < ext::map < SymbolType, unsigned > > >::parse ( input );

    auto mOccPrefixSum = core::xmlApi < ext::map < SymbolType, unsigned > >::parse ( input );
    auto kOcc = core::xmlApi < ext::map < SymbolType, unsigned > >::parse ( input );

    auto markedSymbol = core::xmlApi < SymbolType >::parse ( input );
    auto sparseFirstToText = core::xmlApi < ext::vector < unsigned > >::parse ( input );

    sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, xmlTagName ( ));

    return indexes::stringology::SimpleFMIndex < SymbolType > ( str, superBucketSize, bucketSize,
                                                                superBucketOcc, bucketOcc,
                                                                mOccPrefixSum, kOcc,
                                                                markedSymbol, sparseFirstToText );
}

template < class SymbolType >
bool xmlApi < indexes::stringology::SimpleFMIndex < SymbolType > >::first (
        const ext::deque < sax::Token >::const_iterator & input ) {
    return sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, xmlTagName ( ));
}

template < class SymbolType >
std::string xmlApi < indexes::stringology::SimpleFMIndex < SymbolType > >::xmlTagName ( ) {
    return "SimpleFMIndex";
}

template < class SymbolType >
void xmlApi < indexes::stringology::SimpleFMIndex < SymbolType > >::compose ( ext::deque < sax::Token > & output,
                                                                              const indexes::stringology::SimpleFMIndex < SymbolType > & data ) {
    output.emplace_back ( xmlTagName ( ), sax::Token::TokenType::START_ELEMENT );

    core::xmlApi < string::LinearStringTerminatingSymbolBWT < SymbolType > >::compose ( output, data.getString ( ));

    core::xmlApi < unsigned >::compose ( output, data.getSuperBucketSize ( ));
    core::xmlApi < unsigned >::compose ( output, data.getBucketSize ( ));
    core::xmlApi < ext::vector < ext::map < SymbolType, unsigned > > >::compose ( output, data.getSuperBucketOcc ( ));
    core::xmlApi < ext::vector < ext::map < SymbolType, unsigned > > >::compose ( output, data.getBucketOcc ( ));

    core::xmlApi < ext::map < SymbolType, unsigned > >::compose ( output, data.getMOccPrefixSum ( ));
    core::xmlApi < ext::map < SymbolType, unsigned > >::compose ( output, data.getKOcc ( ));

    core::xmlApi < SymbolType >::compose ( output, data.getMarkedSymbol ( ));
    core::xmlApi < ext::vector < unsigned > >::compose ( output, data.getSparseFirstToText ( ));

    output.emplace_back ( xmlTagName ( ), sax::Token::TokenType::END_ELEMENT );
}

} /* namespace core */

