//Blog post: https://simulinkforsoftwareengineers.blogspot.com/2021/09/hiding-simulation-details-in-c-library.html
#include "SimAPI.h"
#include<map>
using namespace std;

#include<SimState.h> //this is internal to simulation, which the library user does not need to know
#include<Solver.h> //this is internal to simulation

class Simulation {
public:
	State state; //State is defined in SimState.h
	Solver solver; //Solver is defined in Solver.h
};

Simulation* sim;
static map<int, Simulation*> sims;

SimAPI::SimAPI(int simKey) {
	if (sims.count(simKey) > 0) throw SimKeyAlreadyExistsException(simKey);
	sim = new Simulation();
	sims.insert({ simKey, sim });
}

SimAPI::~SimAPI() {} //Note: The desctructor is called right after constructor when this class is used like SimAPI s = SimAPI(...) due to a temp object being created. It is not the case for SimAPI* s = new SimAPI(...).

Outputs SimAPI::runOneStep(int simKey, int timeStep_s) {
	Simulation* pSim = sims[simKey];
	State currentState = pSim->state;
	State newState = pSim->solver(currentState, timeStep_s);
	pSim->state = newState; //update simulation state
	Outputs out = Outputs();
	out.time_s = newState.time_s;
	out.hMSL_m = newState.hMSL_m;
	return out;
}

void SimAPI::terminate(int simKey) {
	sims.erase(simKey);
}