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

#include <learn/ConnT__learn__intConnector.hpp>

#include <learn/PV__learn__intPort.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__intPort * get_p1(const QPR__learn__intPort & qpr, const InterV__learn__intConnector &civ){
  return dynamic_cast<PV__learn__intPort *>(getPortValue(qpr, civ));
}
static inline PV__learn__intPort * get_p2(const QPR__learn__intPort & qpr, const InterV__learn__intConnector &civ){
  return dynamic_cast<PV__learn__intPort *>(getPortValue(qpr, civ));
}


ConnT__learn__intConnector::ConnT__learn__intConnector(const string &name, QPR__learn__intPort &p1, QPR__learn__intPort &p2) : Connector(name), p1(p1), p2(p2) {
    this->addPort(p1);
    this->addPort(p2);

    // Interactions
    _i__p1_p2 = new Inter__learn__intConnector(*this, true, true);
}

ConnT__learn__intConnector::~ConnT__learn__intConnector() {

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

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

    // to avoid warnings
    PortValue *pv = NULL;

    return *pv;
}

void ConnT__learn__intConnector::down(InteractionValue &interactionValue) const {
    assert(dynamic_cast<const InterV__learn__intConnector *>(&interactionValue) != NULL);
    const Inter__learn__intConnector *c_interaction __attribute__((unused)) = static_cast<const Inter__learn__intConnector *>(&(interactionValue.interaction()));
    const InterV__learn__intConnector *c_interaction_v __attribute__((unused)) = static_cast<const InterV__learn__intConnector *>(&interactionValue);
    if(*c_interaction == *_i__p1_p2) {
    // /home/siemens/bip/examples/sync_lec/learn.bip:14:22
        get_p2(p2, *c_interaction_v)->set_d(get_p1(p1, *c_interaction_v)->get_d());
    }
}

void ConnT__learn__intConnector::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__intConnector::createInteraction() const{
    Inter__learn__intConnector *ret = NULL;

    ret = new Inter__learn__intConnector(*this);

    return *ret;
}

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

    ret = new Inter__learn__intConnector(*this, ports);

    return *ret;
}

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

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

    return *ret;
}

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

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

bool ConnT__learn__intConnector::guard(const InteractionValue &interactionValue) const {
    assert(dynamic_cast<const InterV__learn__intConnector *>(&interactionValue) != NULL);
    const InterV__learn__intConnector *c_interaction_v __attribute__((unused)) = static_cast<const InterV__learn__intConnector *>(&interactionValue);
    const Inter__learn__intConnector *c_interaction __attribute__((unused)) = &(c_interaction_v->mInteraction);


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

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

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

  return definedInteractions;
}
