#ifndef LIBWCCL_OPS_MATCH_APPLYOPERATOR_H
#define LIBWCCL_OPS_MATCH_APPLYOPERATOR_H

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

namespace Wccl {

class ConjConditions;
class MatchAction;
/**
 * 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_conditions "match" sections of apply; conditions for finding matches
	  * @param actions "actions" section of apply, should not be empty; actions to apply on matches
	  * @param conditions "cond" section of apply, empty by default; conditions for applying the actions
	  */
	ApplyOperator(
			const VariableAccessor<Match>& matches,
			const boost::shared_ptr<const ConjConditions>& match_conditions,
			const boost::shared_ptr<const std::vector<boost::shared_ptr<MatchAction> > >& actions,
			const boost::shared_ptr<const BoolFunctionPtrVector>& apply_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 ConjConditions> match_conditions_;
	const boost::shared_ptr<const std::vector<boost::shared_ptr<MatchAction> > > actions_;
	const boost::shared_ptr<const std::vector<boost::shared_ptr<Function<Bool> > > > apply_conditions_;
};

} /* end ns Wccl */

#endif // LIBWCCL_OPS_MATCH_APPLYOPERATOR_H