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

#ifndef FF_SOLUTION_H
#define FF_SOLUTION_H

#include "common/lazyvec.h"
#include <vector>
#include <iosfwd>
#include <cassert>

namespace ff {
    
    class IntegerConstraint;
    class ConstConstraint;
    class VarConstraint;
    class NullConstraint;
    class System;	
    class Location;
    class Variable;
    typedef int32_t raw_t;

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

    class Supporter {
    public:
	const Variable* var;
	int32_t value;

	Supporter() : var(NULL), value(0) {}
	Supporter(const Variable* var, int32_t value) : 
	    var(var), value(value) {}	

	bool equals(const Supporter& other) const;
	std::ostream& display(std::ostream& o) const;
    };

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

    class Level {
    public:
	const System* system;
	// TODO: use lazyvec (profiling revealed, that this isn't critical)
	std::vector<Supporter> supporters;
	std::vector<bool> locations;
	std::vector<raw_t> raws;
	std::vector<bool> edges;
	
	Level(const System* system);
	
	std::ostream& display(std::ostream& o) const;
    };

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

    class RelaxedSolution {	
    public:
	LazyVec<Level> levels;
	const System* system;
	RelaxedSolution(const System* system) : system(system) {}
	
	void add(const Location* loc);
	void add(const Supporter& supp);
	void add(const Supporter& supp, int32_t level);

	void add(const IntegerConstraint* ic);
	void add(const VarConstraint* c);
	void add(const ConstConstraint* c);
	void add(const NullConstraint* c);

	void appendLevel();
	void clear();
	Level& operator[](uint32_t level);
	const Level& operator[](uint32_t level) const;
	uint32_t size() const;
	std::ostream& display(std::ostream& o) const;
    };

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

    inline void RelaxedSolution::appendLevel() {
	levels.push_back(Level(system));
    }
    
    inline void RelaxedSolution::clear() {
	levels.clear();
    }
    
    inline Level& RelaxedSolution::operator[](uint32_t level) {
	assert(level < levels.size());
	return levels[level];
    }

    inline const Level& RelaxedSolution::operator[](uint32_t level) const {
	assert(level < levels.size());
	return levels[level];
    }
    
    inline uint32_t RelaxedSolution::size() const {
	return levels.size();
    }
    
    inline std::ostream& operator<<(std::ostream& o, const Level& l) {
	return l.display(o);
    }

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

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

#endif /* FF_SOLUTION_H */
