/*
 * SuffixTrieNodeTerminatingSymbol.h
 *
 *  Created on: Nov 23, 2013
 *      Author: Stepan Plachy
 */

#ifndef SUFFIX_TRIE_NODE_TERMINATING_SYMBOL_H_
#define SUFFIX_TRIE_NODE_TERMINATING_SYMBOL_H_

#include <common/DefaultSymbolType.h>
#include <alib/map>
#include <alib/set>
#include <core/xmlApi.hpp>

namespace indexes {

class SuffixTrieTerminatingSymbol;

/**
 * Represents a node in the ranked tree. Contains name of the symbol.
 */
class SuffixTrieNodeTerminatingSymbol {
protected:
	ext::map < DefaultSymbolType, SuffixTrieNodeTerminatingSymbol * > m_children;

	SuffixTrieNodeTerminatingSymbol * parent;

	/**
	 * Parent tree contanining this instance of RankedTree
	 */
	const SuffixTrieTerminatingSymbol * parentTree;

	/**
	 * @copydoc SuffixTrieNodeTerminatingSymbol::attachTree()
	 */
	bool attachTree ( const SuffixTrieTerminatingSymbol * tree );

public:
	explicit SuffixTrieNodeTerminatingSymbol ( ext::map < DefaultSymbolType, SuffixTrieNodeTerminatingSymbol * > children );

	SuffixTrieNodeTerminatingSymbol ( const SuffixTrieNodeTerminatingSymbol & other );
	SuffixTrieNodeTerminatingSymbol ( SuffixTrieNodeTerminatingSymbol && other ) noexcept;
	SuffixTrieNodeTerminatingSymbol & operator =( const SuffixTrieNodeTerminatingSymbol & other );
	SuffixTrieNodeTerminatingSymbol & operator =( SuffixTrieNodeTerminatingSymbol && other ) noexcept;
	~SuffixTrieNodeTerminatingSymbol ( ) noexcept;

	/**
	 * @copydoc SuffixTrieNodeTerminatingSymbol::clone ( ) const &
	 */
	SuffixTrieNodeTerminatingSymbol * clone ( ) const &;

	/**
	 * @copydoc SuffixTrieNodeTerminatingSymbol::clone ( ) const &
	 */
	SuffixTrieNodeTerminatingSymbol * clone ( ) &&;

	/**
	 * @copydoc RankedNode::computeMinimalAlphabet()
	 */
	ext::set < DefaultSymbolType > computeMinimalAlphabet ( ) const;

	/**
	 * @copydoc SuffixTrieNodeTerminatingSymbol::computeMinimalAlphabet()
	 */
	void computeMinimalAlphabet ( ext::set < DefaultSymbolType > & alphabet ) const;

	/**
	 * @return children
	 */
	const ext::map < const DefaultSymbolType, const SuffixTrieNodeTerminatingSymbol * > & getChildren ( ) const;

	/**
	 * @return children
	 */
	const ext::map < DefaultSymbolType, SuffixTrieNodeTerminatingSymbol * > & getChildren ( );

	SuffixTrieNodeTerminatingSymbol & getChild ( const DefaultSymbolType & symbol );

	const SuffixTrieNodeTerminatingSymbol & getChild ( const DefaultSymbolType & symbol ) const;

	bool hasChild ( const DefaultSymbolType & symbol ) const;

	SuffixTrieNodeTerminatingSymbol & addChild ( DefaultSymbolType symbol, SuffixTrieNodeTerminatingSymbol node );

	SuffixTrieNodeTerminatingSymbol * getParent ( );

	const SuffixTrieNodeTerminatingSymbol * getParent ( ) const;

	void swap ( SuffixTrieNodeTerminatingSymbol & other );

	int compare ( const SuffixTrieNodeTerminatingSymbol & ) const;

	/**
	 * @copydoc SuffixTrieNodeTerminatingSymbol::testSymbol() const
	 */
	bool testSymbol ( const DefaultSymbolType & symbol ) const;

	/**
	 * @copydoc SuffixTrieNodeTerminatingSymbol::operator>>() const
	 */
	void operator >>( std::ostream & out ) const;

	friend std::ostream & operator <<( std::ostream &, const SuffixTrieNodeTerminatingSymbol & node );

	explicit operator std::string ( ) const;

	friend class SuffixTrieTerminatingSymbol;
};

} /* namespace indexes */

namespace ext {

template < >
struct compare < indexes::SuffixTrieNodeTerminatingSymbol > {
	int operator ()( const indexes::SuffixTrieNodeTerminatingSymbol & first, const indexes::SuffixTrieNodeTerminatingSymbol & second ) const {
		return first.compare ( second );
	}

};

} /* namespace ext */

#endif /* SUFFIX_TRIE_NODE_TERMINATING_SYMBOL_H_ */
