/*
 * NonlinearFullAndLinearIndexConstruction.h
 *
 *  Created on: 13. Apr 2017
 *      Author: Jan Travnicek
 */

#ifndef ARBOLOGY_NONLINEAR_FULL_AND_LINEAR_INDEX_CONSTRUCTION_H_
#define ARBOLOGY_NONLINEAR_FULL_AND_LINEAR_INDEX_CONSTRUCTION_H_

#include <indexes/arbology/NonlinearFullAndLinearIndex.h>
#include <tree/ranked/PrefixRankedTree.h>
#include <tree/properties/SubtreeJumpTable.h>
#include <tree/properties/ExactSubtreeRepeatsNaive.h>
#include <stringology/indexing/PositionHeapNaive.h>

namespace arbology {

namespace indexing {

/**
 * Constructs a compressed bit parallel index for given tree.
 *
 */

class NonlinearFullAndLinearIndexConstruction {
public:
	/**
	 * Creates compressed bit parallel index for trees
	 * @param tree tree to construct the index for
	 * @return the index
	 */
	template < class SymbolType, template < typename > class StringIndex = indexes::stringology::PositionHeap, class StringIndexConstructionAlgo = stringology::indexing::PositionHeapNaive >
	static indexes::arbology::NonlinearFullAndLinearIndex < SymbolType, StringIndex > construct ( const tree::PrefixRankedTree < SymbolType > & w );

	template < class SymbolType, template < typename > class StringIndex = indexes::stringology::PositionHeap, class StringIndexConstructionAlgo = stringology::indexing::PositionHeapNaive >
	static indexes::arbology::NonlinearFullAndLinearIndex < SymbolType, StringIndex > construct ( const tree::PrefixRankedBarTree < SymbolType > & w );
};

template < class SymbolType, template < typename > class StringIndex, class StringIndexConstructionAlgo >
indexes::arbology::NonlinearFullAndLinearIndex < SymbolType, StringIndex > NonlinearFullAndLinearIndexConstruction::construct ( const tree::PrefixRankedTree < SymbolType > & w ) {
	ext::vector < common::ranked_symbol < unsigned > > content = tree::properties::ExactSubtreeRepeatsNaive::repeats ( w ).getContent ( );

	ext::vector < unsigned > repeats;
	for ( const common::ranked_symbol < unsigned > & symbol : content )
		repeats.push_back ( symbol.getSymbol ( ) );

	return indexes::arbology::NonlinearFullAndLinearIndex < SymbolType, StringIndex > ( StringIndexConstructionAlgo::construct ( string::LinearString < common::ranked_symbol < SymbolType > > ( w ) ), tree::properties::SubtreeJumpTable::compute ( w ), repeats );
}

template < class SymbolType, template < typename > class StringIndex, class StringIndexConstructionAlgo >
indexes::arbology::NonlinearFullAndLinearIndex < SymbolType, StringIndex > NonlinearFullAndLinearIndexConstruction::construct ( const tree::PrefixRankedBarTree < SymbolType > & w ) {
	ext::vector < common::ranked_symbol < unsigned > > content = tree::properties::ExactSubtreeRepeatsNaive::repeats ( w ).getContent ( );

	ext::vector < unsigned > repeats;
	for ( const common::ranked_symbol < unsigned > & symbol : content )
		repeats.push_back ( symbol.getSymbol ( ) );

	return indexes::arbology::NonlinearFullAndLinearIndex < SymbolType, StringIndex > ( StringIndexConstructionAlgo::construct ( string::LinearString < common::ranked_symbol < SymbolType > > ( w ) ), tree::properties::SubtreeJumpTable::compute ( w ), std::move ( repeats ) );
}

} /* namespace indexing */

} /* namespace arbology */

#endif /* ARBOLOGY_NONLINEAR_FULL_AND_LINEAR_INDEX_CONSTRUCTION_H_ */
