#pragma once

{{ if not is_test_mode- }}
{{ if has_fixed_read_only- }}
#ifndef {package_macro}
#define {package_macro}(FLAG) {package_macro}_##FLAG
#endif
{{ for item in class_elements }}
{{ -if item.is_fixed_read_only }}
#ifndef {package_macro}_{item.flag_macro}
#define {package_macro}_{item.flag_macro} {item.default_value}
#endif
{{ -endif }}
{{ -endfor }}
{{ -endif }}
{{ -endif }}

#ifdef __cplusplus

#include <memory>

namespace {cpp_namespace} \{

class flag_provider_interface \{
public:
    virtual ~flag_provider_interface() = default;
    {{ -for item in class_elements}}
    virtual bool {item.flag_name}() = 0;

    {{ -endfor }}

    {{ -if is_test_mode }}
    {{ -for item in class_elements}}
    virtual void {item.flag_name}(bool val) = 0;
    {{ -endfor }}

    virtual void reset_flags() \{}
    {{ -endif }}
};

extern std::unique_ptr<flag_provider_interface> provider_;

{{ for item in class_elements}}
inline bool {item.flag_name}() \{
    {{ -if is_test_mode }}
    return provider_->{item.flag_name}();
    {{ -else }}
    {{ -if item.readwrite }}
    return provider_->{item.flag_name}();
    {{ -else }}
    {{ -if item.is_fixed_read_only }}
    return {package_macro}_{item.flag_macro};
    {{ -else }}
    return {item.default_value};
    {{ -endif }}
    {{ -endif }}
    {{ -endif }}
}

{{ -if is_test_mode }}
inline void {item.flag_name}(bool val) \{
    provider_->{item.flag_name}(val);
}
{{ -endif }}
{{ -endfor }}

{{ -if is_test_mode }}
inline void reset_flags() \{
    return provider_->reset_flags();
}
{{ -endif }}

}

extern "C" \{
#endif // __cplusplus

{{ for item in class_elements }}
bool {header}_{item.flag_name}();

{{ -if is_test_mode }}
void set_{header}_{item.flag_name}(bool val);
{{ -endif }}
{{ -endfor }}

{{ -if is_test_mode }}
void {header}_reset_flags();
{{ -endif }}

#ifdef __cplusplus
} // extern "C"
#endif

