// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: ffgoal.h 137 2008-02-21 17:38:32Z sebastian $
//
////////////////////////////////////////////////////////////////////

#ifndef FF_GOAL_H
#define FF_GOAL_H

#include "ff_heuristic/ffiguard.h"
#include "ff_heuristic/ffset.h"

#include <inttypes.h>
#include <vector>
#include <iosfwd>

namespace ff {

    // forward declarations 
    class Location;
    
    class Goal {
    private:
	const PtrSet<Location>& reachedLocations;
	std::vector<Location*> locations;
	mutable uint32_t firstNonReached;
	IntegerGuard guard;

	bool allLocationsReached() const;

    public:
	Goal(const PtrSet<Location>& reachedLocations);

	void init();
	void addLocation(Location* loc);
	void addConstraint(IntegerConstraint* ic);
	bool isReached(int32_t level) const;
	
	const std::vector<Location*> getLocations() const { return locations; }
	const IntegerGuard& getGuard() const { return guard; }

	std::ostream& display(std::ostream& o) const;
    };

    ////////////////////////////////////////////////////////////////////

    inline void Goal::init() {
	firstNonReached = 0;
	guard.init();
    }

    inline bool Goal::allLocationsReached() const {
	while (firstNonReached < locations.size() && 
	       reachedLocations.isMember(locations[firstNonReached]))
	{
	    firstNonReached++;
	}
	return firstNonReached == locations.size();
    }
    
    inline bool Goal::isReached(int32_t level) const {
	return allLocationsReached() && guard.isSatisfied(level);
    }

    inline std::ostream& operator<<(std::ostream& o, const Goal& g) {
	return g.display(o);
    }
}

#endif /* FF_GOAL_H */
