#include <libwccl/values/matchvector.h>
#include <libwccl/values/match.h>
#include <libpwrutils/foreach.h>
#include <sstream>
#include <libwccl/exception.h>

namespace Wccl {

std::string MatchVector::to_raw_string() const
{
	std::stringstream ss;
	ss << "MATCH(";
	bool comma = false;
	foreach (const boost::shared_ptr<Match>& m, matches_) {
		if (comma) {
			ss << ",";
		}
		ss << m->to_raw_string();
		comma = true;
	}
	ss << ")";
	return ss.str();
}

Position MatchVector::first_token(const boost::shared_ptr<Corpus2::AnnotatedSentence>& s) const
{
	if (matches_.empty()) {
		return Position(Position::Nowhere);
	} else {
		Position p = matches_.front()->first_token(s);
		for (size_t i = 1; i < matches_.size(); ++i) {
			Position c = matches_[i]->first_token(s);
			if (c.get_value() < p.get_value()) {
				p = c;
			}
		}
		return p;
	}
}

Position MatchVector::last_token(const boost::shared_ptr<Corpus2::AnnotatedSentence>& s) const
{
	if (matches_.empty()) {
		return Position(Position::Nowhere);
	} else {
		Position p = matches_.front()->last_token(s);
		for (size_t i = 1; i < matches_.size(); ++i) {
			Position c = matches_[i]->last_token(s);
			if (c.get_value() > p.get_value()) {
				p = c;
			}
		}
		return p;
	}
}

bool MatchVector::empty() const
{
	foreach (const boost::shared_ptr<Match>& m, matches_) {
		if (!m->empty()) {
			return false;
		}
	}
	return true;
}

void MatchVector::append(const boost::shared_ptr<Match> &m)
{
	matches_.push_back(m);
}

void MatchVector::append(const boost::shared_ptr<MatchVector> &m)
{
	matches_.push_back(boost::shared_ptr<Match>(new Match(m)));
}

void MatchVector::append(const boost::shared_ptr<TokenMatch> &m)
{
	matches_.push_back(boost::shared_ptr<Match>(new Match(m)));
}

void MatchVector::append(const boost::shared_ptr<AnnotationMatch> &m)
{
	matches_.push_back(boost::shared_ptr<Match>(new Match(m)));
}

void MatchVector::append(const boost::shared_ptr<MatchData> &m)
{
	matches_.push_back(boost::shared_ptr<Match>(new Match(m)));
}

const boost::shared_ptr<Match>& MatchVector::submatch(size_t idx)
{
	if (idx < matches_.size()) {
		return matches_[idx];
	} else {
		throw Wccl::WcclError("Match vector index out of range");
	}
}

} /* end ns Wccl */