#pragma once

#ifdef __cplusplus
#include <cstdint>

extern "C"
{
#else
#include <stdint.h>
#endif

    typedef struct CModelSimulation_s
    {
        uint64_t time_ms;
        uint64_t stepTime_ms;
        void *implementation;
        uint8_t isPersistent;
    } CModelSimulation_ts;

    typedef void(CppModelInit_tf)(CModelSimulation_ts *self, unsigned long stepTime_ms);
    typedef void(CppModelRunStep_tf)(CModelSimulation_ts *self, unsigned long stepTime_ms);
    typedef void(CppModelFinalize_tf)(CModelSimulation_ts *self, unsigned long stepTime_ms);

    CModelSimulation_ts *CppModel_create(const char name[], unsigned long totalTime, unsigned long stepTime_ms);
    CModelSimulation_ts *CppModel_createPersistent(const char name[], unsigned long totalTime, unsigned long stepTime_ms);
    void CppModel_destroy(CModelSimulation_ts *self);

    void CppModel_setInitFunction(CModelSimulation_ts *self, CppModelInit_tf *initFunction);
    void CppModel_setRunStepFunction(CModelSimulation_ts *self, CppModelRunStep_tf *runStepFunction);
    void CppModel_setFinalizeFunction(CModelSimulation_ts *self, CppModelFinalize_tf *finalizeFunction);

    uint8_t CppModel_getInputU8(CModelSimulation_ts *self, const char *inputName, uint8_t fallbackValue);
    uint16_t CppModel_getInputU16(CModelSimulation_ts *self, const char *inputName, uint16_t fallbackValue);
    uint32_t CppModel_getInputU32(CModelSimulation_ts *self, const char *inputName, uint32_t fallbackValue);
    int8_t CppModel_getInputI8(CModelSimulation_ts *self, const char *inputName, int8_t fallbackValue);
    int16_t CppModel_getInputI16(CModelSimulation_ts *self, const char *inputName, int16_t fallbackValue);
    int32_t CppModel_getInputI32(CModelSimulation_ts *self, const char *inputName, int32_t fallbackValue);
    float CppModel_getInputF32(CModelSimulation_ts *self, const char *inputName, float fallbackValue);
    double CppModel_getInputF64(CModelSimulation_ts *self, const char *inputName, double fallbackValue);

    void CppModel_setOutputU8(CModelSimulation_ts *self, const char *outputName, uint8_t value);
    void CppModel_setOutputU16(CModelSimulation_ts *self, const char *outputName, uint16_t value);
    void CppModel_setOutputU32(CModelSimulation_ts *self, const char *outputName, uint32_t value);
    void CppModel_setOutputI8(CModelSimulation_ts *self, const char *outputName, int8_t value);
    void CppModel_setOutputI16(CModelSimulation_ts *self, const char *outputName, int16_t value);
    void CppModel_setOutputI32(CModelSimulation_ts *self, const char *outputName, int32_t value);
    void CppModel_setOutputF32(CModelSimulation_ts *self, const char *outputName, float value);
    void CppModel_setOutputF64(CModelSimulation_ts *self, const char *outputName, double value);

    uint8_t CppModel_getOutputU8(CModelSimulation_ts *self, const char *outputName);
    uint16_t CppModel_getOutputU16(CModelSimulation_ts *self, const char *outputName);
    uint32_t CppModel_getOutputU32(CModelSimulation_ts *self, const char *outputName);
    int8_t CppModel_getOutputI8(CModelSimulation_ts *self, const char *outputName);
    int16_t CppModel_getOutputI16(CModelSimulation_ts *self, const char *outputName);
    int32_t CppModel_getOutputI32(CModelSimulation_ts *self, const char *outputName);
    float CppModel_getOutputF32(CModelSimulation_ts *self, const char *outputName);
    double CppModel_getOutputF64(CModelSimulation_ts *self, const char *outputName);

    uint8_t CppModel_getParameterU8(CModelSimulation_ts *self, const char *parameterName, uint8_t fallbackValue);
    uint16_t CppModel_getParameterU16(CModelSimulation_ts *self, const char *parameterName, uint16_t fallbackValue);
    uint32_t CppModel_getParameterU32(CModelSimulation_ts *self, const char *parameterName, uint32_t fallbackValue);
    int8_t CppModel_getParameterI8(CModelSimulation_ts *self, const char *parameterName, int8_t fallbackValue);
    int16_t CppModel_getParameterI16(CModelSimulation_ts *self, const char *parameterName, int16_t fallbackValue);
    int32_t CppModel_getParameterI32(CModelSimulation_ts *self, const char *parameterName, int32_t fallbackValue);
    float CppModel_getParameterF32(CModelSimulation_ts *self, const char *parameterName, float fallbackValue);
    double CppModel_getParameterF64(CModelSimulation_ts *self, const char *parameterName, double fallbackValue);

    void CppModel_Simulate(CModelSimulation_ts *self);

    int CppModel_getSimulationResult(CModelSimulation_ts *self);

    void CppModel_requireNonInteractive(const char *testName);

#ifdef __cplusplus
}
#endif