#ifndef LIBWCCL_VALUES_POSITIONREF_H
#define LIBWCCL_VALUES_POSITIONREF_H

#include <libwccl/values/position.h>
#include <boost/make_shared.hpp>

namespace Wccl {

class PositionRef
{
public:

	explicit PositionRef(const boost::shared_ptr<Position>& base,
			int offset = 0)
		: base_(base), offset_(offset)
	{
		assert(base_);
	}

	explicit PositionRef(int base, int offset = 0)
		: base_(boost::make_shared<Position>(base)), offset_(offset)
	{
	}

	std::string to_raw_string() const;

	const boost::shared_ptr<Position>& get_base() const {
		return base_;
	}

	int get_offset() const {
		return offset_;
	}

	void set_offset(int offset) {
		offset_ = offset;
	}

	/**
	 * Returns true if underlying Position is Nowhere,
	 * or underlying Position is Begin and offset is less than zero,
	 * or underlying Position is End and offset is greater than zero.
	 * False otherwise.
	 * This function does not take into account any actual sentence
	 * boundaries.
	 */
	bool points_nowhere() const {
		//We probably could allow null dereference (shouldn't logically
		//happen so if it does, it's bad) but let's be defensive
		//and assume null base is like nowhere.
		return (base_.get() == NULL) ||
				(base_->get_value() == Position::Nowhere) ||
				(base_->get_value() == Position::Begin && offset_ < 0) ||
				(base_->get_value() == Position::End && offset_ > 0);
	}

	bool equals(const PositionRef& other) {
		return points_nowhere() ? other.points_nowhere()
			: offset_ == other.offset_ && base_->equals(*other.base_);
	}

private:
	boost::shared_ptr<Position> base_;

	int offset_;
};

} /* end ns Wccl */

#endif // LIBWCCL_VALUES_POSITIONREF_H