#include "Deploy.hpp"
#include <fmi2Functions.h>
#include <fmi2FunctionTypes.h>
#include <Variables.hpp>

int main(int argc, char **argv) {
    int ret = EXIT_SUCCESS;

	
    // deploy the system corresponding to the root component
    //Component &component = *deploy(argc, argv);
    // create an engine launcher
    //Launcher launcher(argc, argv, component);
    void * c  = fmi2Instantiate("prModel", fmi2CoSimulation , "prModel", "resource/location", NULL, true, true);

    
    inverted_map[100] = "ROOT.environment._id__inputIndex";
    inverted_map[101] = "ROOT.environment._id__time";
    inverted_map[102] = "ROOT.camera._id__inputIndex";
    inverted_map[103] = "ROOT.perception._id__inputIndex";
    inverted_map[104] = "ROOT.perception._id__result";
    inverted_map[105] = "ROOT.controller._id__speed";
    inverted_map[106] = "ROOT.controller._id__speedLimit";
    inverted_map[107] = "ROOT.controller._id__deltaSpeed";
    inverted_map[108] = "ROOT.controller._id__zero";
    inverted_map[109] = "ROOT.brake._id__deltaSpeed";
    inverted_map[110] = "ROOT.throttle._id__deltaSpeed";
    inverted_map[111] = "ROOT.speedSensor._id__speed";
    inverted_map[112] = "ROOT.speedSensor._id__deltaSpeed";
    const unsigned int vr[] = {100,101,102,103,104,105,106,107,108,109,110,111,112};
    const int values[] = {1,10,0,0,0,0,0,0,0,0,0,100,0};
    fmi2SetInteger(c, vr, 13, values);
    fmi2Integer values2[] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
    
    // initialize the launcher (components, etc.)
    //ret = launcher.initialize();
    fmi2EnterInitializationMode(c);
    int i=0;
    while(i<70){
        i++;
        fmi2GetInteger(c, vr, 13, values2);
        fmi2DoStep(c, 0.5,0.6, true);}
    
    // run the engine
    /*if (ret == EXIT_SUCCESS) {
        //ret = launcher.launch();
        while(1){
        fmi2DoStep(c, 0.5,0.6, true);
        }
    }*/

    return ret;
}

Component* deploy(int argc __attribute__((unused)), char **argv __attribute__((unused))){
    // Top is Comp__ROOT





    staticallocated::port__ROOT__environment__sendInput.addInternalPort(staticallocated::iport__ROOT__environment__sendInput);

    staticallocated::port__ROOT__environment__getInput.addInternalPort(staticallocated::iport__ROOT__environment__getInput);

    staticallocated::port__ROOT__environment__getInputInitial.addInternalPort(staticallocated::iport__ROOT__environment__getInputInitial);

    staticallocated::port__ROOT__environment__noInput.addInternalPort(staticallocated::iport__ROOT__environment__noInput);

    // Runtime init for Atom: Comp__ROOT__environment
    // staticallocated::Comp__ROOT__environment




    staticallocated::port__ROOT__camera__capture.addInternalPort(staticallocated::iport__ROOT__camera__capture);

    staticallocated::port__ROOT__camera__sendInput.addInternalPort(staticallocated::iport__ROOT__camera__sendInput);

    // Runtime init for Atom: Comp__ROOT__camera
    // staticallocated::Comp__ROOT__camera





    staticallocated::port__ROOT__perception__getInput.addInternalPort(staticallocated::iport__ROOT__perception__getInput);

    staticallocated::port__ROOT__perception__sendResult.addInternalPort(staticallocated::iport__ROOT__perception__sendResult);

    staticallocated::port__ROOT__perception__inference.addInternalPort(staticallocated::iport__ROOT__perception__inference);

    // Runtime init for Atom: Comp__ROOT__perception
    // staticallocated::Comp__ROOT__perception







    staticallocated::port__ROOT__controller__getSpeedLimit.addInternalPort(staticallocated::iport__ROOT__controller__getSpeedLimit);

    staticallocated::port__ROOT__controller__getSpeed.addInternalPort(staticallocated::iport__ROOT__controller__getSpeed);

    staticallocated::port__ROOT__controller__brake.addInternalPort(staticallocated::iport__ROOT__controller__brake);

    staticallocated::port__ROOT__controller__throttle.addInternalPort(staticallocated::iport__ROOT__controller__throttle);

    staticallocated::port__ROOT__controller__noSpeedChange.addInternalPort(staticallocated::iport__ROOT__controller__noSpeedChange);

    // Runtime init for Atom: Comp__ROOT__controller
    // staticallocated::Comp__ROOT__controller




    staticallocated::port__ROOT__brake__brake.addInternalPort(staticallocated::iport__ROOT__brake__brake);

    staticallocated::port__ROOT__brake__changeSpeed.addInternalPort(staticallocated::iport__ROOT__brake__changeSpeed);

    // Runtime init for Atom: Comp__ROOT__brake
    // staticallocated::Comp__ROOT__brake




    staticallocated::port__ROOT__throttle__throttle.addInternalPort(staticallocated::iport__ROOT__throttle__throttle);

    staticallocated::port__ROOT__throttle__changeSpeed.addInternalPort(staticallocated::iport__ROOT__throttle__changeSpeed);

    // Runtime init for Atom: Comp__ROOT__throttle
    // staticallocated::Comp__ROOT__throttle




    staticallocated::port__ROOT__speedSensor__getSpeed.addInternalPort(staticallocated::iport__ROOT__speedSensor__getSpeed);

    staticallocated::port__ROOT__speedSensor__changeSpeed.addInternalPort(staticallocated::iport__ROOT__speedSensor__changeSpeed);

    // Runtime init for Atom: Comp__ROOT__speedSensor
    // staticallocated::Comp__ROOT__speedSensor






































    // Runtime init for Compound: Comp__ROOT
    // staticallocated::Comp__ROOT

    // Finished: Comp__ROOT
    return &(staticallocated::Comp__ROOT);
}

bool isSerializeEnabled() {
    return false;
}

void serialize(char **cbuf __attribute__((unused)), size_t *clen __attribute__((unused))){
    assert(false);
}

void deserialize(const char *buf __attribute__((unused)), size_t len __attribute__((unused))){
    assert(false);
}
