#ifndef PREDICATEAND_H
#define PREDICATEAND_H
#include "PredicateSimple.h"
#include "PsimagLite.h"
#include "Vector.h"

namespace PsimagLite
{

/* PSIDOC PredicateAnd
 PredicateAnd is a &-separated list of simple predicates,

 SimplePredicate0&SimplePredicate1&...

 where & means to AND the predicates.
 */
class PredicateAnd
{

public:

	typedef Vector<PredicateSimple>::Type VectorPredicateSimpleType;
	typedef PredicateSimple::VectorStringType VectorStringType;

	PredicateAnd(String pred, PsimagLite::String sep = "&")
	    : pred_(pred)
	{
		VectorStringType tokens;
		split(tokens, pred, sep);
		const SizeType n = tokens.size();
		for (SizeType i = 0; i < n; ++i)
			vPredicateSimple_.push_back(PredicateSimple(tokens[i]));
	}

	template <typename T>
	bool isTrue(String name, T val)
	{
		VectorStringType names { name };
		typename Vector<T>::Type values { val };
		SizeType n = vPredicateSimple_.size();
		for (SizeType i = 0; i < n; ++i)
			if (!vPredicateSimple_[i].isTrue(names, values))
				return false;
		return true;
	}

	template <typename T>
	bool isTrue(String name1, T val1, String name2, T val2)
	{
		VectorStringType names { name1, name2 };
		typename Vector<T>::Type values { val1, val2 };
		SizeType n = vPredicateSimple_.size();
		for (SizeType i = 0; i < n; ++i)
			if (!vPredicateSimple_[i].isTrue(names, values))
				return false;
		return true;
	}

	template <typename T>
	bool isTrue(String name1, T val1, String name2, T val2, String name3, T val3)
	{
		VectorStringType names { name1, name2, name3 };
		typename Vector<T>::Type values { val1, val2, val3 };
		SizeType n = vPredicateSimple_.size();
		for (SizeType i = 0; i < n; ++i)
			if (!vPredicateSimple_[i].isTrue(names, values))
				return false;
		return true;
	}

	template <typename T>
	bool isTrue(String name1, T val1, String name2, T val2, String name3, T val3, String name4, T val4)
	{
		VectorStringType names { name1, name2, name3, name4 };
		typename Vector<T>::Type values { val1, val2, val3, val4 };
		SizeType n = vPredicateSimple_.size();
		for (SizeType i = 0; i < n; ++i)
			if (!vPredicateSimple_[i].isTrue(names, values))
				return false;
		return true;
	}

private:

	String pred_;
	VectorPredicateSimpleType vPredicateSimple_;
};
} // namespace PsimagLite
#endif // PREDICATEAND_H
