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

#ifndef SEARCH_TRACE_H
#define SEARCH_TRACE_H

#include <deque>
#include <inttypes.h>
#include <iosfwd>

class State;
class System;
class Transition;

class Trace {
private:
    const System* system;
    typedef std::deque<const State*> list_t;
    list_t trace;
    
    std::ostream& dumpLocations(const State* state, std::ostream& o) const;
    std::ostream& dumpVariables(const State* state, std::ostream& o) const;
    std::ostream& dumpZone(const State* state, std::ostream& o) const;
    std::ostream& dumpTransition(const Transition* trans, std::ostream& o) const;

public:
    typedef list_t::const_iterator const_iterator;
    typedef list_t::iterator iterator;

    Trace(const System* system);
    
    void backchain(const State* state);
    uint32_t size() const { return trace.size(); }

    const State* operator[](uint32_t index) { return trace[index]; }
    const State* operator[](uint32_t index) const { return trace[index]; }

    const_iterator begin() const { return trace.begin(); }
    const_iterator end() const { return trace.end(); }

    iterator begin() { return trace.begin(); }
    iterator end() { return trace.end(); }    

    const State* back() const { return trace.back(); }
    const State* back() { return trace.back(); }
    
    void prepend(const State* state) { trace.push_front(state); }
    void append(const State* state) { trace.push_back(state); }

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

    uint32_t length() const { return trace.size() - 1; }

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

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

#endif /* SEARCH_TRACE_H */
