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

#ifndef SEARCH_TRANSITION_H
#define SEARCH_TRANSITION_H

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

#include "system/edge.h"

class Edge;
class System;

class Transition {
private:
    Transition();
    Transition(const Edge* edge1, const Edge* edge2, uint32_t uid);
public:
    const Edge* edge1;
    const Edge* edge2;
    uint32_t uid;

    std::ostream& display(std::ostream& o) const;
    bool operator==(const Transition& other) const;
    bool operator!=(const Transition& other) const;
    friend class TransitionBuilder;
};

inline bool Transition::operator==(const Transition& other) const {
    return uid == other.uid;
}

inline bool Transition::operator!=(const Transition& other) const {
    return uid == other.uid;
}

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

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

class TransitionBuilder {
private:
    typedef std::vector<std::vector<Transition> > map_t;
    const uint32_t nrEdges;
    std::vector<Transition*> alltrans;
    std::vector<std::vector<Transition*> > trans;
    uint32_t nrTransitions;

    TransitionBuilder(const System* system);
    TransitionBuilder(const TransitionBuilder&);
    TransitionBuilder& operator=(const TransitionBuilder&);

public:
    static TransitionBuilder& builder(const System* system=NULL);

    const std::vector<Transition*>& getAllTransitions() const;
    const Transition* newTransition(const Edge* edge1, const Edge* edge2) const;
    const Transition* newTransition(const Edge* edge1) const;
    const Transition* getTransition(uint32_t id) const;    
    
    uint32_t getNrTransitions() const;
};

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

inline const Transition* TransitionBuilder::getTransition(uint32_t id) const {
    return alltrans[id];
}

inline const std::vector<Transition*>& TransitionBuilder::getAllTransitions() const {
    return alltrans;
}

inline uint32_t TransitionBuilder::getNrTransitions() const {
    return nrTransitions;
}

inline const Transition* TransitionBuilder::newTransition(const Edge* edge1) const {
    assert(trans[edge1->idInSystem][nrEdges]);
    return trans[edge1->idInSystem][nrEdges];
}

inline const Transition* TransitionBuilder::newTransition(const Edge* edge1, const Edge* edge2) const {
    assert(trans[edge1->idInSystem][edge2->idInSystem]);	
    return trans[edge1->idInSystem][edge2->idInSystem]; 	
}

#endif /* SEARCH_TRANSITION_H */
