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

#pragma once

#include <indexes/stringology/BWTAuxiliaryData.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>

namespace core {

template < class SymbolType >
struct xmlApi < indexes::stringology::BWTAuxiliaryData < SymbolType > > {
    static indexes::stringology::BWTAuxiliaryData < 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::BWTAuxiliaryData < SymbolType > & index );
};

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

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

    res.setDataTypeBitmask ( core::xmlApi < unsigned >::parse ( input ));

    sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "OrderedSymbolSet" );
    ext::set < SymbolType, alphabet::SymbolCompare < SymbolType > > orderedAlphabet;
    while ( sax::FromXMLParserHelper::isTokenType ( input, sax::Token::TokenType::START_ELEMENT ))
        orderedAlphabet.insert ( core::xmlApi < SymbolType >::parse ( input ));
    sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "OrderedSymbolSet" );
    res.setOrderedAlphabet ( orderedAlphabet );

    res.setTerminatingSymbolIndex ( core::xmlApi < unsigned >::parse ( input ));

    res.setCPrefixOcc ( core::xmlApi < ext::vector < unsigned >>::parse ( input ));
    res.setKOcc ( core::xmlApi < ext::map < SymbolType, unsigned >>::parse ( input ));
    res.setMOccPrefixSum ( core::xmlApi < ext::map < SymbolType, unsigned >>::parse ( input ));

    res.setVReverseDecode ( core::xmlApi < ext::vector < unsigned >>::parse ( input ));
    res.setWForwardDecode ( core::xmlApi < ext::vector < unsigned >>::parse ( input ));

    res.setHrTextToFirst ( core::xmlApi < ext::vector < unsigned >>::parse ( input ));
    res.setIFirstToText ( core::xmlApi < ext::vector < unsigned >>::parse ( input ));

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

template < class SymbolType >
bool xmlApi < indexes::stringology::BWTAuxiliaryData < 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::BWTAuxiliaryData < SymbolType > >::xmlTagName ( ) {
    return "BWTAuxiliaryData";
}

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

    core::xmlApi < unsigned >::compose ( output, data.getDataTypeBitmask ( ));

    output.emplace_back ( "OrderedSymbolSet", sax::Token::TokenType::START_ELEMENT );
    for ( const auto & symbol : data.getOrderedAlphabet ( ))
        core::xmlApi < SymbolType >::compose ( output, symbol );
    output.emplace_back ( "OrderedSymbolSet", sax::Token::TokenType::END_ELEMENT );

    core::xmlApi < unsigned >::compose ( output, data.getTerminatingSymbolIndex ( ));

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

    core::xmlApi < ext::vector < unsigned > >::compose ( output, data.getVReverseDecode ( ));
    core::xmlApi < ext::vector < unsigned > >::compose ( output, data.getWForwardDecode ( ));

    core::xmlApi < ext::vector < unsigned > >::compose ( output, data.getHrTextToFirst ( ));
    core::xmlApi < ext::vector < unsigned > >::compose ( output, data.getIFirstToText ( ));

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

} /* namespace core */

