#pragma once
#include <vector>
#include <libsumo/TraCIDefs.h>
#ifndef LIBTRACI
class PositionVector;
#endif
namespace LIBSUMO_NAMESPACE {
class Simulation {
public:
static std::pair<int, std::string> init(int port = 8813, int numRetries = libsumo::DEFAULT_NUM_RETRIES,
const std::string& host = "localhost", const std::string& label = "default", FILE* const pipe = nullptr);
static std::pair<int, std::string> start(const std::vector<std::string>& cmd, int port = -1, int numRetries = libsumo::DEFAULT_NUM_RETRIES,
const std::string& label = "default", const bool verbose = false,
const std::string& traceFile = "", bool traceGetters = true, void* _stdout = nullptr);
static bool isLibsumo();
static void switchConnection(const std::string& label);
static const std::string& getLabel();
static void setOrder(int order);
static void load(const std::vector<std::string>& args);
static bool hasGUI();
static bool isLoaded();
static void step(const double time = 0.);
static void executeMove();
static void close(const std::string& reason = "Libsumo requested termination.");
static std::pair<int, std::string> getVersion();
static std::string getOption(const std::string& option);
static int getCurrentTime();
static double getTime();
static double getEndTime();
static int getLoadedNumber();
static std::vector<std::string> getLoadedIDList();
static int getDepartedNumber();
static std::vector<std::string> getDepartedIDList();
static int getArrivedNumber();
static std::vector<std::string> getArrivedIDList();
static int getParkingStartingVehiclesNumber();
static std::vector<std::string> getParkingStartingVehiclesIDList();
static int getParkingEndingVehiclesNumber();
static std::vector<std::string> getParkingEndingVehiclesIDList();
static int getStopStartingVehiclesNumber();
static std::vector<std::string> getStopStartingVehiclesIDList();
static int getStopEndingVehiclesNumber();
static std::vector<std::string> getStopEndingVehiclesIDList();
static int getCollidingVehiclesNumber();
static std::vector<std::string> getCollidingVehiclesIDList();
static int getEmergencyStoppingVehiclesNumber();
static std::vector<std::string> getEmergencyStoppingVehiclesIDList();
static int getStartingTeleportNumber();
static std::vector<std::string> getStartingTeleportIDList();
static int getEndingTeleportNumber();
static std::vector<std::string> getEndingTeleportIDList();
static int getDepartedPersonNumber();
static std::vector<std::string> getDepartedPersonIDList();
static int getArrivedPersonNumber();
static std::vector<std::string> getArrivedPersonIDList();
static std::vector<std::string> getBusStopIDList();
static int getBusStopWaiting(const std::string& stopID);
static std::vector<std::string> getBusStopWaitingIDList(const std::string& stopID);
static std::vector<std::string> getPendingVehicles();
static std::vector<libsumo::TraCICollision> getCollisions();
static double getScale();
static double getDeltaT();
static libsumo::TraCIPositionVector getNetBoundary();
static int getMinExpectedNumber();
static libsumo::TraCIPosition convert2D(const std::string& edgeID, double pos, int laneIndex = 0, bool toGeo = false);
static libsumo::TraCIPosition convert3D(const std::string& edgeID, double pos, int laneIndex = 0, bool toGeo = false);
static libsumo::TraCIRoadPosition convertRoad(double x, double y, bool isGeo = false, const std::string& vClass = "ignoring");
static libsumo::TraCIPosition convertGeo(double x, double y, bool fromGeo = false);
static double getDistance2D(double x1, double y1, double x2, double y2, bool isGeo = false, bool isDriving = false);
static double getDistanceRoad(const std::string& edgeID1, double pos1, const std::string& edgeID2, double pos2, bool isDriving = false);
static libsumo::TraCIStage findRoute(const std::string& fromEdge, const std::string& toEdge, const std::string& vType = "", const double depart = -1., const int routingMode = 0);
static std::vector<libsumo::TraCIStage> findIntermodalRoute(const std::string& fromEdge, const std::string& toEdge, const std::string& modes = "",
double depart = -1., const int routingMode = 0, double speed = -1., double walkFactor = -1.,
double departPos = 0, double arrivalPos = libsumo::INVALID_DOUBLE_VALUE, const double departPosLat = 0,
const std::string& pType = "", const std::string& vType = "", const std::string& destStop = "");
static std::string getParameter(const std::string& objectID, const std::string& key);
static const std::pair<std::string, std::string> getParameterWithKey(const std::string& objectID, const std::string& key);
static void setParameter(const std::string& objectID, const std::string& key, const std::string& value);
static void setScale(double value);
static void clearPending(const std::string& routeID = "");
static void saveState(const std::string& fileName);
static double loadState(const std::string& fileName);
static void writeMessage(const std::string& msg);
LIBSUMO_SUBSCRIPTION_API
static void subscribe(const std::vector<int>& varIDs = std::vector<int>({-1}), double begin = libsumo::INVALID_DOUBLE_VALUE, double end = libsumo::INVALID_DOUBLE_VALUE, const libsumo::TraCIResults& parameters = libsumo::TraCIResults());
static const libsumo::TraCIResults getSubscriptionResults();
#ifndef LIBTRACI
#ifndef SWIG
static void storeShape(PositionVector& shape);
static std::shared_ptr<VariableWrapper> makeWrapper();
static bool handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData);
#endif
#endif
private:
#ifndef LIBTRACI
static SubscriptionResults mySubscriptionResults;
static ContextSubscriptionResults myContextSubscriptionResults;
#ifdef HAVE_FOX
static FXMutex myStepMutex;
#endif
#endif
Simulation() = delete;
};
}