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

#include <learn/AT__learn__Camera.hpp>

#include <iostream>
#include <sstream>

#include <CycleInAtomPrioritiesError.hpp>
#include <NonDeterministicPetriNetError.hpp>
#include <NonOneSafePetriNetError.hpp>
#include <AtomInvariantViolationError.hpp>
#include <Variables.hpp>


bool AT__learn__Camera::atIdle () const {
    return __statesbv[ 0/(8*sizeof(int))] & 1<< (0%(8*sizeof(int)));
}

bool AT__learn__Camera::toIdle () {
    if (atIdle()) return false;
    __statesbv[ 0/(8*sizeof(int))] |= 1<< (0%(8*sizeof(int)));
    return true;
}

bool AT__learn__Camera::fromIdle () {
    if (!atIdle()) return false;
    __statesbv[ 0/(8*sizeof(int))] &= ~(1<< (0%(8*sizeof(int))));
    return true;
}

bool AT__learn__Camera::atRead () const {
    return __statesbv[ 1/(8*sizeof(int))] & 1<< (1%(8*sizeof(int)));
}

bool AT__learn__Camera::toRead () {
    if (atRead()) return false;
    __statesbv[ 1/(8*sizeof(int))] |= 1<< (1%(8*sizeof(int)));
    return true;
}

bool AT__learn__Camera::fromRead () {
    if (!atRead()) return false;
    __statesbv[ 1/(8*sizeof(int))] &= ~(1<< (1%(8*sizeof(int))));
    return true;
}

AT__learn__Camera::AT__learn__Camera(const string &name , AtomIPort__learn__intPort &_iport_decl__capture, AtomIPort__learn__intPort &_iport_decl__sendInput
                         
                         , AtomEPort__learn__intPort &_eport_decl__capture, AtomEPort__learn__intPort &_eport_decl__sendInput
                         
                         ) :  ComponentItf(name, ATOM), Atom(name) , _iport_decl__capture(_iport_decl__capture), _iport_decl_pv__capture(_id__inputIndex, this->fullName()+"._id__inputIndex"), _iport_decl__sendInput(_iport_decl__sendInput), _iport_decl_pv__sendInput(_id__inputIndex, this->fullName()+"._id__inputIndex"), _eport_decl__capture(_eport_decl__capture), _eport_decl__sendInput(_eport_decl__sendInput), _transguard__1(false), _transguard__2(false), __previous(-1) {
    this->addInternalPort(_iport_decl__capture);

    // link data internal to internal port
    this->addInternalPort(_iport_decl__sendInput);
    // export port
    this->addPort(_eport_decl__capture);
    this->addPort(_eport_decl__sendInput);
}

BipError& AT__learn__Camera::execute(PortValue &portValue) {
    BipError *ret = &BipError::NoError;

#ifndef NDEBUG
    bool something_happened = false;
#endif

    // find the right transitions to execute
    if ((&_iport_decl_pv__capture == &portValue) && _transguard__1) {
        // check consistency (enabledness, port values, ...)
        assert(_iport_decl__capture.hasPortValue());
        assert(&_iport_decl__capture.portValue() == &portValue);

        // check at most one transitions is executed
        assert(!something_happened);

        // the transition should be enabled by places
        assert(atIdle());

        // update input places
        fromIdle();

        // check one-safetyness
        if (atRead()) {
            NonOneSafePetriNetError *r = new NonOneSafePetriNetError(*this);
            r->setPort(_iport_decl__capture);
            return *r;
        }

        // update output places
        toRead();

        // record the index of the latest executed transition
        __previous = 1;
// /home/siemens/bip/examples/sync_lec/learn.bip:52:2



        
#ifndef NDEBUG
        something_happened = true;
#endif
    } else if ((&_iport_decl_pv__sendInput == &portValue) && _transguard__2) {
        // check consistency (enabledness, port values, ...)
        assert(_iport_decl__sendInput.hasPortValue());
        assert(&_iport_decl__sendInput.portValue() == &portValue);

        // check at most one transitions is executed
        assert(!something_happened);

        // the transition should be enabled by places
        assert(atRead());

        // update input places
        fromRead();

        // check one-safetyness
        if (atIdle()) {
            NonOneSafePetriNetError *r = new NonOneSafePetriNetError(*this);
            r->setPort(_iport_decl__sendInput);
            return *r;
        }

        // update output places
        toIdle();

        // record the index of the latest executed transition
        __previous = 2;
// /home/siemens/bip/examples/sync_lec/learn.bip:53:2



        
#ifndef NDEBUG
        something_happened = true;
#endif
    }
    if (ret->type() != NO_ERROR) return *ret;

    // check that at least one transition has been executed
    assert(something_happened);

    // execute internal transitions
    ret = &executeInternalTransitions();

    if (ret->type() != NO_ERROR) return *ret;

    return update();
}

BipError& AT__learn__Camera::execute(AtomExternalPort &port) {
   BipError *ret = &BipError::NoError;

#ifndef NDEBUG
    bool something_happened = false;
#endif

    if (ret->type() != NO_ERROR) return *ret;

    // check that at least one transition has been executed
    assert(something_happened);

    // execute internal transitions
    ret = &executeInternalTransitions();

    if (ret->type() != NO_ERROR) return *ret;

    return update();
}

BipError& AT__learn__Camera::initialize() {
    BipError *ret = &BipError::NoError;
    
    // reset status of ports
    _iport_decl__capture.clearPortValue();
    _iport_decl__sendInput.clearPortValue();

    // reset status of transitions
    _transguard__1 = false;
    _transguard__2 = false;

    // initialize to empty marking
    for (unsigned int idx = 0; idx < bvector_size; idx++){
        __statesbv[idx] = 0;
    }

    // marking must be initialized to empty
    assert((!atIdle()) && (!atRead()));

    // update initial places
    toIdle();

    // record the index of the latest executed transition
    __previous = 0;




    if (ret->type() != NO_ERROR) return *ret;

    // execute (initial) internal transitions
    ret = &executeInternalTransitions();

    if (ret->type() != NO_ERROR) return *ret;

    return update();
}

string AT__learn__Camera::toString() const {
    ostringstream oss;
    bool first=true;
    if (atIdle()) {
      if (!first) oss << ", ";
      else {
        first = false;
        oss << "at ";
      }
      oss << "Idle";
    }
    if (atRead()) {
      if (!first) oss << ", ";
      else {
        first = false;
        oss << "at ";
      }
      oss << "Read";
    }

    if (first) first = false;
    else oss << std::endl;
    oss << "inputIndex=" << _id__inputIndex;

    return oss.str(); 
}

BipError& AT__learn__Camera::update() {
    BipError *ret = &BipError::NoError;

    // update status of internal/external ports w.r.t. transitions
    // reset status of port capture
    this->_iport_decl__capture.setIsEnabled(false);
    
    _transguard__1 = (atIdle()
    
                );
    
    if (_transguard__1) {
        if (_iport_decl__capture.isEnabled()) {
            NonDeterministicPetriNetError *r = new NonDeterministicPetriNetError(*this);
            r->setPort(_iport_decl__capture);
        
            return *r;
        }
        
        _iport_decl__capture.setIsEnabled(true);
    }
    
    // reset status of port sendInput
    this->_iport_decl__sendInput.setIsEnabled(false);
    
    _transguard__2 = (atRead()
    
                );
    
    if (_transguard__2) {
        if (_iport_decl__sendInput.isEnabled()) {
            NonDeterministicPetriNetError *r = new NonDeterministicPetriNetError(*this);
            r->setPort(_iport_decl__sendInput);
        
            return *r;
        }
        
        _iport_decl__sendInput.setIsEnabled(true);
    }
    // recompute modified priority paths
    
    // applies priorities to port capture
    
    // recompute modified priority paths
    
    // applies priorities to port sendInput
    
    // update port value of capture
    if (this->_iport_decl__capture.isEnabled() && !this->_iport_decl__capture.isDisabledByPriorities()) {
        this->_iport_decl__capture.setPortValue(_iport_decl_pv__capture);
    }
    else {
        this->_iport_decl__capture.clearPortValue();
    }
    
    // update port value of sendInput
    if (this->_iport_decl__sendInput.isEnabled() && !this->_iport_decl__sendInput.isDisabledByPriorities()) {
        this->_iport_decl__sendInput.setPortValue(_iport_decl_pv__sendInput);
    }
    else {
        this->_iport_decl__sendInput.clearPortValue();
    }
    
    // force recomputation of connectors involving capture
    _eport_decl__capture.setIsReset(true);
    
    // recompute port values of capture from scratch
    this->_eport_decl__capture.portValues().clear();
    
    // check port value of capture exported by capture
    if (this->_iport_decl__capture.hasPortValue()) {
        this->_eport_decl__capture.addPortValue(_iport_decl_pv__capture);
    }
    
    // force recomputation of connectors involving sendInput
    _eport_decl__sendInput.setIsReset(true);
    
    // recompute port values of sendInput from scratch
    this->_eport_decl__sendInput.portValues().clear();
    
    // check port value of sendInput exported by sendInput
    if (this->_iport_decl__sendInput.hasPortValue()) {
        this->_eport_decl__sendInput.addPortValue(_iport_decl_pv__sendInput);
    }

    return *ret;
}

BipError &AT__learn__Camera::executeInternalTransitions() {
    BipError &ret = BipError::NoError;

    // used to record the enabled internal transition
    int __enabled_internal = 0;

    do {
        // recompute enabled internal transitions
        __enabled_internal = 0;


        // execute the enabled internal transition if exist
        if (__enabled_internal != 0) {
            switch (__enabled_internal) {

              default:
                assert(false);
            }
        }
    } while (__enabled_internal != 0);

    return ret;
}

AT__learn__Camera::~AT__learn__Camera() {
}
