
#include <iostream>
#include <boost/chrono/chrono.hpp>
#include "broker.hpp"
#include "client.hpp"

int main(int argc, char** argv) {

    {%set broker = stinger.get_example_broker()%}
    auto conn = std::make_shared<{{broker.class_name}}>({%if broker.hostname is none%}"localhost", 1883, {%endif%}"{{stinger.cpp.client_class_name}}-demo");
    {{stinger.cpp.client_class_name}} client(conn);

    {%-for sig_name, sig in stinger.signals.items() %}
    client.register{{sig_name | UpperCamelCase}}Callback([]({%for arg in sig.arg_list%}{{arg.cpp_type}} {{arg.name}}{%if not loop.last%}, {%endif%}{%endfor%}) {
        std::cout << {%for arg in sig.arg_list%}"{{arg.name}}=" << {%-if arg.optional%} "None"{%else%}{%if arg.arg_type.name.lower() == 'enum'%}{{arg.enum.name | camelCase }}Strings[static_cast<int>({{arg.name}})]{%else%}{{arg.name}}{%endif%}{%endif%} << {%if not loop.last %}" | " << {%endif%}{%endfor%} std::endl;
    });
    {%-endfor%}

    {%-for method_name, method in stinger.methods.items() %}
    std::cout << "Calling {{method_name}}" << std::endl;
    auto {{method_name|camelCase}}ResultFuture = client.{{method_name | camelCase}}({%for arg in method.arg_list%}{{arg.get_random_example_value('c++')}}{%if not loop.last%}, {%endif%}{%endfor%});
    auto {{method_name|camelCase}}Status = {{method_name|camelCase}}ResultFuture.wait_for(boost::chrono::seconds(5));
    if ({{method_name|camelCase}}Status == boost::future_status::timeout)
    {
        std::cout << "TIMEOUT after 5 seconds waiting for {{method_name}} response." << std::endl;
    }
    else
    {
        {%if method.return_value_type == 'primitive'-%}
        std::cout << "Result: {{method.return_value.name | UpperCamelCase}}=" << {{method_name|camelCase}}ResultFuture.get() << std::endl;
        {%elif method.return_value_type == 'enum'-%}
        std::cout << "Result: {{method.return_value.name | UpperCamelCase}}=" << {{method.return_value.enum.name | camelCase }}Strings[{{method_name|camelCase}}ResultFuture.get()] << std::endl;
        {%elif method.return_value_type == 'struct'-%}
        {{method.return_value_cpp_class}} returnValue = {{method_name|camelCase}}ResultFuture.get();
        std::cout << "Results:"{%for m in method.return_value%} << " {{m.name}}=" << {%if m.arg_type.name.lower() == 'enum'%}{{m.enum.name | camelCase }}Strings[static_cast<int>(returnValue.{{m.name}})]{%else%}returnValue.{{m.name}}{%endif%} {%endfor%} << std::endl;
        {%endif%}
    }
    {%-endfor%}

    std::cout << "Connected and waiting.  Use Ctrl-C to exit." << std::endl;

    while (true) {
        sleep(10);
    }

    return 0;
}