{% from "helper_macros.j2" import print_template_info, insert_block, cpp_type, print_license_header %}
{{ print_license_header(info.license_header) }}
#ifndef {{ info.hpp_guard }}
#define {{ info.hpp_guard }}

{{ print_template_info('2', 'marked regions will be kept') }}

#include "{{ info.ld_ev_header }}"

{% for impl in provides %}
{% if loop.first %}
// headers for provided interface implementations
{% endif %}
#include <{{ impl.base_class_header }}>
{% endfor %}

{% for interface in requires %}
{% if loop.first %}
// headers for required interface implementations
{% endif %}
#include <{{ interface.exports_header }}>
{% endfor %}

{{ insert_block(info.blocks.add_headers) }}

namespace module {

struct Conf {
    {% for item in info.module_config %}
    {{ cpp_type(item) }} {{ item.name }};
    {% endfor %}
};

class {{ info.class_name }} : public Everest::ModuleBase {
public:
    {{ info.class_name }}() = delete;
    {{ info.class_name }}(
        const ModuleInfo& info,
        {% if info.enable_external_mqtt %}
        Everest::MqttProvider& mqtt_provider,
        {% endif %}
        {% if info.enable_telemetry %}
        Everest::TelemetryProvider& telemetry,
        {% endif %}
        {% for impl in provides %}
        std::unique_ptr<{{ impl.base_class }}> p_{{ impl.id }},
        {% endfor %}
        {% for requirement in requires %}
        {% if requirement.is_vector %}
        std::vector<std::unique_ptr<{{ requirement.class_name }}>> r_{{ requirement.id }},
        {% else %}
        std::unique_ptr<{{ requirement.class_name }}> r_{{ requirement.id }},
        {% endif %}
        {% endfor %}
        Conf& config
    ) :
        ModuleBase(info),
        {% if info.enable_external_mqtt %}
        mqtt(mqtt_provider),
        {% endif %}
        {% if info.enable_telemetry %}
        telemetry(telemetry),
        {% endif %}
        {% for impl in provides %}
        p_{{ impl.id }}(std::move(p_{{ impl.id }})),
        {% endfor %}
        {% for requirement in requires %}
        r_{{ requirement.id }}(std::move(r_{{ requirement.id }})),
        {% endfor %}
        config(config)
    {};

    {% if info.enable_external_mqtt %}
    Everest::MqttProvider& mqtt;
    {% endif %}
    {% if info.enable_telemetry %}
    Everest::TelemetryProvider& telemetry;
    {% endif %}
    {% for impl in provides %}
    const std::unique_ptr<{{ impl.base_class }}> p_{{ impl.id }};
    {% endfor %}
    {% for requirement in requires %}
    {% if requirement.is_vector %}
    const std::vector<std::unique_ptr<{{ requirement.class_name }}>> r_{{ requirement.id }};
    {% else %}
    const std::unique_ptr<{{ requirement.class_name }}> r_{{ requirement.id }};
    {% endif %}
    {% endfor %}
    const Conf& config;

    {{ insert_block(info.blocks.public_defs, indent=4) }}

protected:
    {{ insert_block(info.blocks.protected_defs, indent=4) }}

private:
    friend class LdEverest;
    void init();
    void ready();

    {{ insert_block(info.blocks.private_defs, indent=4) }}

};

{{ insert_block(info.blocks.after_class) }}

} // namespace module

#endif // {{ info.hpp_guard }}
