// /home/siemens/bip/examples/sync_lec/learn.bip:22:1

#include <learn/ConnT__learn__singleton.hpp>

#include <learn/PV__learn__silent.hpp>


static inline PortValue * getPortValue(const QuotedPortReference & qpr, const InteractionValue &civ){
    Port &p = qpr.port();
    vector<Port *>::size_type idx = 0;
    for (vector<Port *>::const_iterator i = civ.ports().begin();
         i != civ.ports().end();
         i++, idx++){
        if (&p == *i) break;
    }
    assert (idx < civ.ports().size()); // means we couldn't find corresponding port value 
    return civ.portValues()[idx];
}

static inline PV__learn__silent * get_p1(const QPR__learn__silent & qpr, const InterV__learn__singleton &civ){
  return dynamic_cast<PV__learn__silent *>(getPortValue(qpr, civ));
}


ConnT__learn__singleton::ConnT__learn__singleton(const string &name, QPR__learn__silent &p1) : Connector(name), p1(p1) {
    this->addPort(p1);
}

ConnT__learn__singleton::~ConnT__learn__singleton() {
    for (vector<Interaction *>::const_iterator interactionIt = definedInteractions.begin() ;
         interactionIt != definedInteractions.end() ;
         ++interactionIt) {
        delete *interactionIt;
    }
    definedInteractions.clear();
}

PortValue &ConnT__learn__singleton::up(const InteractionValue &interactionValue) const {
    // THIS SHOULD *NEVER* HAPPEN.
    assert(false);

    // to avoid warnings
    PortValue *pv = NULL;

    return *pv;
}

void ConnT__learn__singleton::down(InteractionValue &interactionValue) const {
    
}

void ConnT__learn__singleton::down(InteractionValue &interactionValue, PortValue &portValue) const {
    // You should *never* reach this. Calling this method denotes an error in
    // scheduling (the down(interactionvalue) should have been used
    assert(false);
}

Interaction &ConnT__learn__singleton::createInteraction() const{
    Inter__learn__singleton *ret = NULL;

    ret = new Inter__learn__singleton(*this);

    return *ret;
}

Interaction &ConnT__learn__singleton::createInteraction(const vector<Port *> &ports) const{
  Inter__learn__singleton *ret = NULL;

    ret = new Inter__learn__singleton(*this, ports);

    return *ret;
}

InteractionValue &ConnT__learn__singleton::createInteractionValue(const Interaction &interaction, const vector<PortValue *> &values) const {
    InterV__learn__singleton *ret = NULL;

    ret = new InterV__learn__singleton(*this, interaction, values);

    return *ret;
}

void ConnT__learn__singleton::releaseInteraction(Interaction &interaction) const {
    delete &interaction;
}

void ConnT__learn__singleton::releaseInteractionValue(InteractionValue &interactionValue) const {
    delete &interactionValue;
}

bool ConnT__learn__singleton::guard(const InteractionValue &interactionValue) const {


    // default to true. May not be the wisest choice.
    return true;
}

const vector<Interaction*>& ConnT__learn__singleton::interactions() const {
  if (definedInteractions.empty()) {
    definedInteractions.push_back(new Inter__learn__singleton(*this, true));
  }

  // check that the number of defined interactions is correct
  assert(definedInteractions.size() == 1);

  return definedInteractions;
}
