// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: trace.cpp 815 2011-09-10 12:57:27Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#include "trace.h"
#include "transition.h"

#include "system/effect.h"
#include "system/guard.h"
#include "system/process.h"
#include "system/state.h"
#include "system/system.h"
#include "system/variable.h"

using namespace std;

Trace::Trace(const System* system) : 
    system(system),
    trace() 
{}

void Trace::backchain(const State* state) {
    const State* goal = state;
    prepend(goal);
    while (goal->predecessor) {
     	goal = goal->predecessor;
	prepend(goal);
    }
} 

ostream& Trace::dumpLocations(const State* state, ostream& o) const {
    for (uint32_t i = 0; i < system->procs.size(); i++) {
	o << state->proc(i) << endl;
    }
    return o << "." << endl;
}

ostream& Trace::dumpVariables(const State* state, ostream& o) const {
    for (uint32_t i = 0; i < system->getTotalNrIntegers(); i++) {
	o << state->var(i) << endl;
    }
    return o << "." << endl;
}

ostream& Trace::dumpZone(const State* state, ostream& o) const {
    const uint32_t dim = state->zone().getDimension();
    for (uint32_t i = 0; i < dim; i++) {
	for (uint32_t j = 0; j < dim; j++) {
	    if (i != j && state->zone()(i, j) < dbm_INFINITY) {
		o << i << endl;
		o << j << endl;
		o << state->zone()(i, j) << endl << "." << endl;
	    }
	}
    }
    return o << "." << endl;
}

ostream& Trace::dumpTransition(const Transition* trans, ostream& o) const {
    o << trans->edge1->getProcess()->id << " " << (trans->edge1->idInProcess + 1)<< endl;
    if (trans->edge2) {
	o << trans->edge2->getProcess()->id << " " << (trans->edge2->idInProcess + 1)<< endl;
    }
    return o << "." << endl;
}

ostream& Trace::dump(ostream& o) const {
    for (list_t::const_iterator it = trace.begin(); it != trace.end(); ++it) {
	const State* state = *it;

	dumpLocations(state, o);
	dumpZone(state, o);
	dumpVariables(state, o);	

	if (state->reachedby) {
	    dumpTransition(state->reachedby, o);
	}
    }

    return o << "." << endl;
}

ostream& Trace::display(ostream& o) const {
    int32_t i = 0;
    for (list_t::const_iterator it = trace.begin(); it != trace.end(); ++it) {
	const State* state = *it;
	if (state->reachedby) {
	    o << endl << endl << *state->reachedby << endl << endl;
	}

	o << "state: " << i++ << endl;
	state->prettyPrint(o, system);
    }
    return o;
}

