#ifndef ISSUBSETOF_H
#define ISSUBSETOF_H

#include <boost/shared_ptr.hpp>

#include <libcorpus2/tagset.h>

#include <libwccl/values/strset.h>
#include <libwccl/values/tset.h>
#include <libwccl/values/bool.h>
#include <libwccl/ops/setpredicate.h>
#include <libwccl/ops/formatters.h>

namespace Wccl {

/**
 * Class that realises a predicate checking if one set is a subset of another
 */
template <class T>
class IsSubsetOf : public SetPredicate<T>
{
public:
	typedef typename SetPredicate<T>::SetFunctionPtr SetFunctionPtr;

	IsSubsetOf(const SetFunctionPtr& subset_expr, const SetFunctionPtr& set_expr)
		: SetPredicate<T>(subset_expr, set_expr)
	{
	}

	virtual const std::string raw_operator_name() const {
		return "in";
	}

protected:

	typedef typename SetPredicate<T>::BaseRetValPtr BaseRetValPtr;

	/**
	 * Take value of possible subset in question. If it is an empty set, return False.
	 * Otherwise, take value of the set that is being compared to.
	 * Return True if the possible subset is indeed a subset of the compared set,
	 * otherwise return False.
	 */
	virtual BaseRetValPtr apply_internal(const SentenceContext& context) const {
		boost::shared_ptr<T> possible_subset = this->set1_expr_->apply(context);
		if(!possible_subset->empty()) {
			boost::shared_ptr<T> set_compared_to = this->set2_expr_->apply(context);
			if(possible_subset->is_subset_of(*set_compared_to)) {
				return Predicate::True->apply(context);
			}
		}
		return Predicate::False->apply(context);
	}

};

} /* end ns Wccl */


#endif // ISSUBSETOF_H