#ifndef PHYLOCPP_TREE_VALUEACCESSOR_HPP
#define PHYLOCPP_TREE_VALUEACCESSOR_HPP

// Default value accessors

struct TaxonValueAccessor {

	TaxonValueAccessor(){}

	template <typename NodeIterator>
	inline typename NodeIterator::Node::Taxon::value_type & operator()(NodeIterator & it) {
		return it->taxon()->value();
	}

	template <typename NodeIterator>
	inline const typename NodeIterator::Node::Taxon::value_type & operator()(const NodeIterator & it) const {
		return it->taxon()->value();
	}
	
	template <typename NodeIterator>
	inline typename NodeIterator::Node::Taxon::value_type & operator()(NodeIterator * it) {
		return it->taxon()->value();
	}

	template <typename NodeIterator>
	inline const typename NodeIterator::Node::Taxon::value_type & operator()(const NodeIterator * it) const {
		return it->taxon()->value();
	}
};

struct NodeValueAccessor {

	NodeValueAccessor() {}

	template <typename NodeIterator>
	inline typename NodeIterator::Node::value_type & operator()(NodeIterator & it) {
		return it->value();
	}

	template <typename NodeIterator>
	inline const typename NodeIterator::Node::value_type & operator()(const NodeIterator & it) const {
		return it->value();
	}
	
	template <typename NodeIterator>
	inline typename NodeIterator::Node::Taxon::value_type & operator()(NodeIterator * it) {
		return it->value();
	}

	template <typename NodeIterator>
	inline const typename NodeIterator::Node::Taxon::value_type & operator()(const NodeIterator * it) const {
		return it->value();
	}
};

struct EdgeValueAccessor {

	template <typename EdgeIterator>
	inline typename EdgeIterator::Edge::value_type & operator()(const EdgeIterator & it) {
		return it->value();
	}

	template <typename EdgeIterator>
	inline const typename EdgeIterator::Edge::value_type & operator()(const EdgeIterator & it) const {
		return it->value();
	}
};

// Value accessors for elements in indexed containers

template <typename T>
struct TaxonIndexedValueAccessor {

	TaxonIndexedValueAccessor(unsigned int index) : i(index) {}

	template <typename NodeIterator>
	inline T & operator()(const NodeIterator & it) {
		return it->taxon()->value()[i];
	}

	template <typename NodeIterator>
	inline const T & operator()(const NodeIterator & it) const {
		return it->taxon()->value()[i];
	}

	unsigned int i;
};

template <typename T>
struct NodeIndexedValueAccessor {

	NodeIndexedValueAccessor(unsigned int index) : i(index) {}

	template <typename NodeIterator>
	inline T & operator()(const NodeIterator & it) {
		return it->value()[i];
	}

	template <typename NodeIterator>
	inline const T & operator()(const NodeIterator & it) const {
		return it->value()[i];
	}

	unsigned int i;
};

template <typename T>
struct EdgeIndexedValueAccessor {

	EdgeIndexedValueAccessor(unsigned int index) : i(index) {}

	template <typename EdgeIterator>
	inline T & operator()(const EdgeIterator & it) {
		return it->value()[i];
	}

	template <typename EdgeIterator>
	inline const T & operator()(const EdgeIterator & it) const {
		return it->value()[i];
	}

	unsigned int i;
};

#endif // PHYLOCPP_TREE_VALUEACCESSOR_HPP
