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

#ifndef FF_ASSIGN_H
#define FF_ASSIGN_H

#include "ff_heuristic/ffvar.h"
#include <inttypes.h>
#include <iosfwd>

namespace ff {
    
    class FFBackHeuristic;
    //////////////////////////////////////////////////////////////////////
    //
    // An Assignment is the base class of all assignments. So far
    // there are only two types of assignemnts x := y and x:= c where
    // x, y are integer variables and c ins a constant. The apply
    // function returns true if the assignment can be applied multiple
    // times
    //
    //////////////////////////////////////////////////////////////////////

    class IntegerAssignment {
    protected:
	Variable* lhs;
	const int32_t id;

	IntegerAssignment(Variable* lhs, int32_t id) : lhs(lhs), id(id) {}       
    public:
	virtual ~IntegerAssignment() {}
	virtual int32_t getID() const { return id; }
	virtual bool apply() = 0;
	virtual Variable* getLhs() const { return lhs; }
	virtual bool idempotent() const = 0;
	virtual std::ostream& display(std::ostream& o) const = 0;
	virtual bool accept(FFBackHeuristic* heur, int32_t value, int32_t level) const = 0;
    };

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

    ////////////////////////////////////////////////////////////////////
    
    class VarAssignment : public IntegerAssignment {
    public:
	const Variable* rhs;

	VarAssignment(int32_t id, Variable* lhs, Variable* rhs);
	virtual bool apply();
	virtual bool idempotent() const { return false; }
	virtual std::ostream& display(std::ostream& o) const;
	virtual bool accept(FFBackHeuristic* heur, int32_t value, int32_t level) const;
    };

    inline bool VarAssignment::apply() {
	return lhs->add(rhs);
    }

    ////////////////////////////////////////////////////////////////////
    
    class ConstAssignment : public IntegerAssignment {
    public:
	const int32_t rhs;

	ConstAssignment(int32_t id, Variable* lhs, int32_t rhs);
	virtual bool apply();
	virtual bool idempotent() const { return true; }
	virtual std::ostream& display(std::ostream& o) const;
	virtual bool accept(FFBackHeuristic* heur, int32_t value, int32_t level) const;
    };

    inline bool ConstAssignment::apply() {
	return lhs->add(rhs);
    }

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

    class NullAssignment : public IntegerAssignment {
    public:
	NullAssignment() : IntegerAssignment(NULL, -1) {}
	virtual bool apply() { return false; }
	virtual bool idempotent() const { return true; }
	virtual std::ostream& display(std::ostream& o) const;
	virtual bool accept(FFBackHeuristic*, int32_t, int32_t) const { return false; }
    };
}

#endif /* FF_ASSIGN_H */
