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

#include <learn/ConnT__learn__rendezVous.hpp>

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


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

    // Interactions
    _i__p1_p2_p3 = new Inter__learn__rendezVous(*this, true, true, true);
}

ConnT__learn__rendezVous::~ConnT__learn__rendezVous() {

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

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

    // to avoid warnings
    PortValue *pv = NULL;

    return *pv;
}

void ConnT__learn__rendezVous::down(InteractionValue &interactionValue) const {
    assert(dynamic_cast<const InterV__learn__rendezVous *>(&interactionValue) != NULL);
    const Inter__learn__rendezVous *c_interaction __attribute__((unused)) = static_cast<const Inter__learn__rendezVous *>(&(interactionValue.interaction()));
    const InterV__learn__rendezVous *c_interaction_v __attribute__((unused)) = static_cast<const InterV__learn__rendezVous *>(&interactionValue);
    if(*c_interaction == *_i__p1_p2_p3) {
    // /home/siemens/bip/examples/sync_lec/learn.bip:19:25
        get_p2(p2, *c_interaction_v)->set_d(get_p1(p1, *c_interaction_v)->get_d());
    }
}

void ConnT__learn__rendezVous::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__rendezVous::createInteraction() const{
    Inter__learn__rendezVous *ret = NULL;

    ret = new Inter__learn__rendezVous(*this);

    return *ret;
}

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

    ret = new Inter__learn__rendezVous(*this, ports);

    return *ret;
}

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

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

    return *ret;
}

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

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

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


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

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

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

  return definedInteractions;
}
