#include <libwccl/ops/functions/bool/iteration.h>
#include <libwccl/ops/functions/bool/predicate.h>


namespace Wccl {

#ifndef _MSC_VER
const int Iteration::MatchAll;
#endif

Iteration::BaseRetValPtr Iteration::apply_internal(const FunExecContext& context) const
{
	const boost::shared_ptr<const Position>& range_begin = range_begin_expr_->apply(context);
	const boost::shared_ptr<const Position>& range_end = range_end_expr_->apply(context);
	const boost::shared_ptr<Position>& iter_var = context.variables()->get_fast(iter_var_acc_);

	const SentenceContext& sc = context.sentence_context();

	int abs_begin = sc.get_abs_position(*range_begin);
	int abs_end = sc.get_abs_position(*range_end);

	// Proceed only if range positions are not "nowhere".
	if (abs_begin != Position::Nowhere && abs_end != Position::Nowhere) {
		// Trim range to sentence boundaries
		if (abs_begin < 0) {
			abs_begin = 0;
		}
		if (abs_end >= sc.size()) {
			abs_end = sc.size() - 1;
		}
		int range_size = abs_begin - abs_end + 1;
		// Proceed only if range isn't empty
		if (range_size > 0) {
			int n = (match_count_ == MatchAll) ? range_size : match_count_;
			// Proceed only if the range actually has enough positions to match
			if (n <= range_size) {
				if (direction_ == Forward) {
					if (iterate(abs_begin, abs_end, 1, *iter_var, context)) {
						return Predicate::True(context);
					}
				}
				if (iterate(abs_end, abs_begin, -1, *iter_var, context)) {
					return Predicate::True(context);
				}
			}
		}
	}
	// In case of failure, set iteration variable to Nowhere and return False
	iter_var->set_value(Position::Nowhere);
	return Predicate::False(context);
}

bool Iteration::iterate(int start, int stop, int step, Position &p, const FunExecContext &context) const
{
	//TODO: implement
	return false;
}

} /* end ns Wccl */