#ifndef _RAASPECIESTREE_H_
#define _RAASPECIESTREE_H_

extern "C" {
#include "RAA_acnuc.h"
}

#include <string>

namespace bpp {

/**
 * @brief   To work with the species tree classification of the database.
 *
 * The tree can be walked up or down starting from a string, a database species rank,
 * or an NCBI taxonID (TID) value. The species tree also contains synonymous names.
 * The root of the tree is named "ROOT" and has database rank 2.
 */

	
class RaaSpeciesTree {
	friend class RAA;
public:
	
	/**
	 * @brief Returns the database rank of a taxon identified by its name.
	 *
	 * @param  taxon    A taxon name. Case is not significant.
	 * @param allowsynonym  If true, the return value will give the synonym's rank rather than the rank of its
	 * major taxon.
	 * @return The database rank of this taxon, or 0 if no such taxon exists in tree.
	 */
	int findNode(const std::string &taxon, bool allowsynonym = false);
	
	/**
	 * @brief Returns the database rank of a taxon identified by a TID.
	 *
	 * @param  tid     A TID value.
	 * @return The database rank of this taxon, or 0 if no such taxon exists in tree.
	 */
	int findNode(int tid);
	
	/**
	 * @brief Returns the name of a taxon identified by its database rank.
	 *
	 * @param  rank  The database rank of a taxon.
	 * @return The name of this taxon.
	 */
	std::string getName(int rank);
	
	/**
	 * @brief Returns the database rank of the parent of a taxon in the tree.
	 *
	 * @param  rank  The database rank of a taxon.
	 * @return The database rank of the parent of this taxon in the tree, or 0 if no such taxon exists in tree.
	 */
	int parent(int rank);
	
	/**
	 * @brief Returns the TID of a taxon.
	 *
	 * @param  rank  The database rank of a taxon.
	 * @return The TID of this taxon, or 0 if no such taxon exists in tree.
	 */
	int getTid(int rank);
	
	/**
	 * @brief Returns the number of sequences attached to a taxon or to taxa below it in the species tree.
	 *
	 * @param  rank  The database rank of a taxon.
	 * @return The number of sequences attached to this taxon or to taxa below it, or 0 if no such taxon exists in tree.
	 */
	int count(int rank);
	
	/**
	 * @brief Returns the label of a taxon of given rank.
	 *
	 * Labels may contain taxon common names, genetic code information, TID values, and taxonomic 
	 * level information (e.g., genus, order).
	 * @param  rank  The database rank of a taxon.
	 * @return The label of this taxon, or "" if no such taxon or label exists in tree. 
	 */
	std::string label(int rank);
	
	/**
	 * @brief Returns the rank of the first child taxon of a given taxon.
	 *
	 * @param  rank  The database rank of a taxon.
	 * @return The rank of its first child taxon, or 0 if no child taxon exists in tree.
	 */
	int firstChild(int rank);
	
	/**
	 * @brief Allows to loop around all child taxa of a given taxon.
	 *
	 * @param  parent  The database rank of a taxon.
	 * @param  child  The database rank of a child of taxon of rank parent.
	 * @return The rank of the next child taxon of parent after taxon child, or 0 if no more child taxon exists in tree.
	 */
	int nextChild(int parent, int child);
	
	/**
	 * @brief Tells whether there is a downward path from taxon parent to taxon child in the species tree.
	 *
	 * @param  parent  The database rank of a taxon.
	 * @param  child  The database rank of another taxon.
	 * @return true iff child is below parent (possibly with intermediate nodes) in the species tree.
	 */
	bool isChild(int parent, int child);
	
	/**
	 * @brief Allows to loop around all synonymous taxa of a given taxon.
	 *
	 * Synonymous taxa of a taxon are chained in a closed loop, among which only one, the major taxon,
	 * has a parent taxon.
	 *
	 * @param  rank  The database rank of a taxon.
	 * @return  The rank of the next synonymous taxon, or 0 if taxon rank has no synonymous taxon.
	 */
	int nextSynonym(int rank);
	
	/**
	 * @brief Gives the major taxon among all synonyms of a given taxon.
	 *
	 * @param  rank  The database rank of a taxon.
	 * @return  The rank of the major taxon of taxon rank (can be itself).
	 */
	 int getMajor(int rank);
	
private:
	raa_db_access *raa_data;
	raa_node **sp_tree;
	int *tid_to_rank;
	int max_tid;
	int max_sp;
};

} //namespace bpp.

#endif // _RAASPECIESTREE_H_

