#include <sdbusplus/async.hpp>

#include <iostream>
#include <string>
#include <variant>
#include <vector>

auto runner(sdbusplus::async::context& ctx) -> sdbusplus::async::task<>
{
    // Create a proxy to the systemd manager object.
    constexpr auto systemd = sdbusplus::async::proxy()
                                 .service("org.freedesktop.systemd1")
                                 .path("/org/freedesktop/systemd1")
                                 .interface("org.freedesktop.systemd1.Manager");

    // Call ListUnitFiles method.
    using ret_type = std::vector<std::tuple<std::string, std::string>>;
    for (auto& [file, status] :
         co_await systemd.call<ret_type>(ctx, "ListUnitFiles"))
    {
        std::cout << file << " " << status << std::endl;
    }

    // Get the Architecture property.
    std::cout << co_await systemd.get_property<std::string>(ctx, "Architecture")
              << std::endl;

    // Get all the properties.
    using variant_type =
        std::variant<bool, std::string, std::vector<std::string>, uint64_t,
                     int32_t, uint32_t, double>;
    for (auto& [property, value] :
         co_await systemd.get_all_properties<variant_type>(ctx))
    {
        std::cout
            << property << " is "
            << std::visit(
                   // Convert the variant member to a string for printing.
                   [](auto v) {
                       if constexpr (std::is_same_v<
                                         std::remove_cvref_t<decltype(v)>,
                                         std::vector<std::string>>)
                       {
                           return std::string{"Array"};
                       }
                       else if constexpr (std::is_same_v<
                                              std::remove_cvref_t<decltype(v)>,
                                              std::string>)
                       {
                           return v;
                       }
                       else
                       {
                           return std::to_string(v);
                       }
                   },
                   value)
            << std::endl;
    }

    // Try to set the Architecture property (which won't work).
    try
    {
        co_await systemd.set_property(ctx, "Architecture", "arm64");
    }
    catch (const std::exception& e)
    {
        std::cout << "Caught exception because you cannot set Architecture: "
                  << e.what() << std::endl;
    }

    // Create a match for the NameOwnerChanged signal.
    namespace rules = sdbusplus::bus::match::rules;
    auto match = sdbusplus::async::match(ctx, rules::nameOwnerChanged());

    // Listen for the signal 4 times...
    for (size_t i = 0; i < 4; ++i)
    {
        auto [service, old_name, new_name] =
            co_await match.next<std::string, std::string, std::string>();

        if (!new_name.empty())
        {
            std::cout << new_name << " owns " << service << std::endl;
        }
        else
        {
            std::cout << service << " released" << std::endl;
        }
    };

    co_return;
}

int main()
{
    sdbusplus::async::context ctx;
    ctx.run(runner(ctx));

    return 0;
}
