#ifndef LIBWCCL_OPS_MATCH_APPLYOPERATOR_H
#define LIBWCCL_OPS_MATCH_APPLYOPERATOR_H

#include <libwccl/ops/functions/bool/predicates/logicalpredicate.h>

#include <libwccl/ops/match/matchoperator.h>
#include <libwccl/ops/match/matchaction.h>


namespace Wccl {

/**
 * Operator that realizes "apply" functionality for match rules
 */
class ApplyOperator : public Expression
{
public:
	typedef LogicalPredicate::BoolFunctionPtrVector BoolFunctionPtrVector;
	/**
	  * @param matches Accessor to the "$m:_M" variable
	  * @param match_op "match" operator for apply
	  * @param actions "actions" section of apply, should not be empty
	  * @param conditions "cond" section of apply, empty by default
	  */
	ApplyOperator(
			const VariableAccessor<Match>& matches,
			const boost::shared_ptr<const MatchOperator>& match_op,
			const boost::shared_ptr<const std::vector<boost::shared_ptr<MatchAction> > >& actions,
			const boost::shared_ptr<const BoolFunctionPtrVector>& conditions
				= boost::shared_ptr<const BoolFunctionPtrVector>(new BoolFunctionPtrVector()));

	/**
	 * @returns Name of the operator.
	 */
	std::string name() const {
		return "apply";
	}

	/**
	 * @returns String representation of the Action
	 */
	std::string to_string(const Corpus2::Tagset& tagset) const;

	/**
	 * Executes the apply operator on given context.
	 * It iterates current sentence position applying match operator
	 * and if match is found and conditions are met, executes actions.
	 */
	virtual void execute(const ActionExecContext &context) const;

protected:
	/**
	 * Writes string representation of the operator to
	 * an output stream.
	 * @returns Stream written to.
	 * @note May be incomplete and/or containt internal info.
	 */
	std::ostream& write_to(std::ostream& ostream) const;

private:
	const VariableAccessor<Match> _matches;
	const boost::shared_ptr<const MatchOperator> _match_op;
	const boost::shared_ptr<const std::vector<boost::shared_ptr<MatchAction> > > _actions;
	const boost::shared_ptr<const std::vector<boost::shared_ptr<Function<Bool> > > > _conditions;
};

} /* end ns Wccl */

#endif // LIBWCCL_OPS_MATCH_APPLYOPERATOR_H