#include <libwccl/ops/tagrulesequence.h>
#include <libpwrutils/foreach.h>


namespace Wccl {

Bool TagRuleSequence::execute_once(const boost::shared_ptr<Corpus2::Sentence>& sentence)
{
	if(!sentence || sentence->empty()) {
		throw InvalidArgument(
				"sentence",
				"Received an empty sentence.");
	}
	Bool changed(false);
	SentenceContext sc(sentence);
	while(sc.is_current_inside()) {
		foreach (TagRule& rule, *this) {
			if (rule.execute(sc).get_value()) {
				changed.set_value(true);
			}
		}
		sc.advance();
	}
	return changed;
}

int TagRuleSequence::execute_until_done(const boost::shared_ptr<Corpus2::Sentence>& sentence, int max_iter)
{
	if(max_iter < 0) {
		throw InvalidArgument(
				"max_iter",
				"Supplied a negative value for maximum number of iterations.");
	}
	int iter_no = 0;
	while(iter_no < max_iter) {
		++iter_no;
		if (!execute_once(sentence).get_value()) {
			return iter_no;
		}
	}
	return iter_no;
}

std::string TagRuleSequence::to_string(const Corpus2::Tagset& tagset) const
{
	std::ostringstream os;
	os << "tag_rules(";
	for (size_t i = 0; i < size(); ++i) {
		if (i != 0) {
			os << ";\n";
		}
		os << at(i).to_string(tagset);
	}
	os << ")";
	return os.str();
}

std::ostream& TagRuleSequence::write_to(std::ostream &os) const
{
	os << "tag_rules(";
	for (size_t i = 0; i < size(); ++i) {
		if (i != 0) {
			os << ";\n";
		}
		os << at(i);
	}
	os << ")";
	return os;
}

} /* end ns Wccl */