#include <sdbusplus/async.hpp>

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

auto startup(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;
        }
    }

    // We are all done, so shutdown the server.
    ctx.request_stop();

    co_return;
}

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

    return 0;
}
