// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: ffedge.h 184 2008-06-04 13:03:13Z sebastian $
//
////////////////////////////////////////////////////////////////////

#ifndef FF_EDGE_H
#define FF_EDGE_H

#include "ff_heuristic/ffiguard.h"
#include "ff_heuristic/ffassign.h"
#include "ff_heuristic/ffarray.h"
#include <inttypes.h>
#include <iosfwd>
#include <vector>

namespace ff {
    
    // forward declarations
    class Location;
    class IntegerAssignment;
    
    ////////////////////////////////////////////////////////////////////
    //
    // Represents an edge in the abstract transition graph.
    // 
    ////////////////////////////////////////////////////////////////////
    
    class Edge {	
    public:	
	enum type_t { 
	    TAU = 0,
	    BANG,
	    QUE 
	};
	
    private:	
	static uint32_t nrEdges;
	static const int32_t not_activated = -1;
	IntegerGuard iguard;
	std::vector<IntegerAssignment*> assigns;
	std::vector<const Edge*> syncs;
	type_t type;
	uint32_t procID;
	int32_t chanNr;
	mutable int32_t activationLevel;
	mutable bool selected;

    public:	
	Location* to;
	Location* from;	
	const uint32_t id;

	Edge();
	~Edge();

	void addAssignment(IntegerAssignment* ass);
	void addConstraint(IntegerConstraint* ic);
	
	void addSyncEdge(const Edge* edge) { syncs.push_back(edge); }	
	const std::vector<const Edge*>& getSyncEdges() const { return syncs; }

	int32_t  getChannelNr() const;
	void     setChannelNr(int32_t nr);
	
	uint32_t getProcID() const;
	void     setProcID(uint32_t id);

	type_t   getType() const;
	void     setType(type_t t);

	int32_t getActivationLevel() const { return activationLevel; }
	void setActivationLevel(int32_t level) const { 
	    if (activationLevel == not_activated) {
		activationLevel = level; 
	    }
	}

	bool isSelected() const { return selected; }
	void select() const { selected = true; }

	bool isEnabled(int32_t level) const;

	const IntegerGuard& getGuard() const { return iguard; }
	const std::vector<IntegerAssignment*>& getAssignments() const { return assigns; }
	void init();

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

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

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

    inline void Edge::init() {
	selected = false;
	activationLevel = not_activated;
	iguard.init();
    }

    inline bool Edge::isEnabled(int32_t level) const {
	return iguard.isSatisfied(level);
    }

    inline int32_t Edge::getChannelNr() const {
	return chanNr;
    }

    inline void Edge::setChannelNr(int32_t nr) {
	chanNr = nr;
    }

    inline uint32_t Edge::getProcID() const {
	return procID;	    
    }

    inline void Edge::setProcID(uint32_t id) {
	procID = id;
    }
    
    inline Edge::type_t Edge::getType() const {
	return type;
    }

    inline void Edge::setType(type_t t) {
	type = t;
    }          
}

#endif /* FF_EDGE_H */
