// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: domainTransitionGraph.h 823 2011-10-01 14:48:13Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#ifndef DOMAIN_TRANSITION_GRAPH_H
#define DOMAIN_TRANSITION_GRAPH_H

#include "causalgraph/idmapper.h"

#include <map>
#include <vector>
#include <iosfwd>

namespace cg {
    class CGVariable;
    class CGOperator;

    class DomainTransitionGraph {
    public:
	typedef std::vector<std::pair<const CGVariable *, int> > Condition;
    
	struct Transition {
	    Transition(int theTarget, int theOp) : target(theTarget), op(theOp) {}
	    bool operator==(const Transition &other) const {
		
		return target == other.target && condition == other.condition; // && op == other.op;
	    }
	    bool operator<(const Transition &other) const;
	    int target;
	    int op;
	    Condition condition;
	};
    private:
	typedef std::vector<Transition> Vertex;
	std::vector<Vertex> vertices;
	int level;
	std::vector<CGVariable*> all_variables;
	IDMapper procid_to_varid;
	void processEQConstraint(CGVariable* var, int value, Condition& cond);

    public:
	DomainTransitionGraph(const CGVariable* var, const std::vector<CGVariable*>& all_variables, const IDMapper& procid_to_varid);
	// additionalConstraints are needed for varAssignments a:=w, where we need guards w==1, w==2, ... for the corresponding w values
	void addTransition(int from, int to, const CGOperator* op, int op_index, const std::vector<std::pair<CGVariable*, int> >& additionalConstraints);
	void finalize();
	std::ostream& display(std::ostream& o) const;
	bool is_strongly_connected() const;
	std::vector<Transition> get_vertices(int from) { return vertices[from]; }
	int get_level() { return level; }
    };

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

#endif
