#include <boost/asio.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/unpack_properties.hpp>

#include <iostream>

const std::string demoServiceName = "demo.service";
const std::string demoObjectPath = "/xyz/demo";
const std::string demoInterfaceName = "xyz.demo";
const std::string propertyGrettingName = "Greetings";
const std::string propertyGoodbyesName = "Goodbyes";
const std::string propertyValueName = "Value";

class Application
{
  public:
    Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
                sdbusplus::asio::object_server& objServer) :
        ioc_(ioc),
        bus_(bus), objServer_(objServer)
    {
        demo_ =
            objServer_.add_unique_interface(demoObjectPath, demoInterfaceName);

        demo_->register_property_r(propertyGrettingName, std::string(),
                                   sdbusplus::vtable::property_::const_,
                                   [this](const auto&) { return greetings_; });

        demo_->register_property_rw(
            propertyGoodbyesName, std::string(),
            sdbusplus::vtable::property_::emits_change,
            [this](const auto& newPropertyValue, const auto&) {
                goodbyes_ = newPropertyValue;
                return 1;
            },
            [this](const auto&) { return goodbyes_; });

        demo_->register_property_r(
            propertyValueName, uint32_t{42},
            sdbusplus::vtable::property_::const_,
            [](const auto& value) -> uint32_t { return value; });

        demo_->initialize();
    }

    uint32_t fatalErrors() const
    {
        return fatalErrors_;
    }

    auto logSystemErrorCode(boost::system::error_code ec)
    {
        std::cerr << "Error: " << ec << "\n";
        ++fatalErrors_;
    }

    void logException(const std::exception& e)
    {
        std::cerr << "Error: " << e.what() << "\n";
        ++fatalErrors_;
    }

    void logBadProperty(const std::string& badProperty)
    {
        std::cerr << "BadProperty: " << badProperty << "\n";
        ++fatalErrors_;
    }

    void logExpectedException(
        const sdbusplus::exception::UnpackPropertyError& error)
    {
        std::cout << "As expected " << error.what() << " => "
                  << error.propertyName << " is missing because "
                  << error.reason << "\n";
    }

    void asyncGetAllPropertiesStringTypeOnly()
    {
        sdbusplus::asio::getAllProperties(
            bus_, demoServiceName, demoObjectPath, demoInterfaceName,
            [this](boost::system::error_code ec,
                   std::vector<std::pair<
                       std::string, std::variant<std::monostate, std::string>>>&
                       properties) -> void {
                if (ec)
                {
                    logSystemErrorCode(ec);
                    return;
                }
                {
                    std::string greetings;
                    std::string goodbyes;
                    std::optional<std::string> badProperty =
                        sdbusplus::unpackPropertiesNoThrow(
                            properties, propertyGrettingName, greetings,
                            propertyGoodbyesName, goodbyes);

                    if (badProperty)
                    {
                        logBadProperty(*badProperty);
                    }
                    else
                    {
                        std::cout << "value of greetings: " << greetings
                                  << "\n";
                        std::cout << "value of goodbyes: " << goodbyes << "\n";
                    }
                }

                try
                {
                    std::string value;
                    sdbusplus::unpackProperties(properties, propertyValueName,
                                                value);

                    std::cerr << "Error: it should fail because of "
                                 "not matched type\n";
                    ++fatalErrors_;
                }
                catch (const sdbusplus::exception::UnpackPropertyError& error)
                {
                    logExpectedException(error);
                }
            });
    }

    void asyncGetAllProperties()
    {
        sdbusplus::asio::getAllProperties(
            bus_, demoServiceName, demoObjectPath, demoInterfaceName,
            [this](boost::system::error_code ec,
                   std::vector<std::pair<
                       std::string,
                       std::variant<std::monostate, std::string, uint32_t>>>&
                       properties) -> void {
                if (ec)
                {
                    logSystemErrorCode(ec);
                    return;
                }
                try
                {
                    std::string greetings;
                    std::string goodbyes;
                    uint32_t value = 0u;
                    sdbusplus::unpackProperties(properties,
                                                propertyGrettingName, greetings,
                                                propertyGoodbyesName, goodbyes,
                                                propertyValueName, value);

                    std::cout << "value of greetings: " << greetings << "\n";
                    std::cout << "value of goodbyes: " << goodbyes << "\n";
                    std::cout << "value of value: " << value << "\n";
                }
                catch (const sdbusplus::exception::UnpackPropertyError& error)
                {
                    logException(error);
                }

                try
                {
                    std::string unknownProperty;
                    sdbusplus::unpackProperties(
                        properties, "UnknownPropertyName", unknownProperty);

                    std::cerr << "Error: it should fail because of "
                                 "missing property\n";
                    ++fatalErrors_;
                }
                catch (const sdbusplus::exception::UnpackPropertyError& error)
                {
                    logExpectedException(error);
                }

                try
                {
                    uint32_t notMatchingType;
                    sdbusplus::unpackProperties(
                        properties, propertyGrettingName, notMatchingType);

                    std::cerr << "Error: it should fail because of "
                                 "not matched type\n";
                    ++fatalErrors_;
                }
                catch (const sdbusplus::exception::UnpackPropertyError& error)
                {
                    logExpectedException(error);
                }
            });
    }

  private:
    boost::asio::io_context& ioc_;
    sdbusplus::asio::connection& bus_;
    sdbusplus::asio::object_server& objServer_;

    std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
    std::string greetings_ = "Hello";
    std::string goodbyes_ = "Bye";

    uint32_t fatalErrors_ = 0u;
};

int main(int, char**)
{
    boost::asio::io_context ioc;
    boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);

    signals.async_wait(
        [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });

    auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
    auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);

    bus->request_name(demoServiceName.c_str());

    Application app(ioc, *bus, *objServer);

    boost::asio::post(ioc,
                      [&app] { app.asyncGetAllPropertiesStringTypeOnly(); });
    boost::asio::post(ioc, [&app] { app.asyncGetAllProperties(); });

    ioc.run();

    std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";

    return app.fatalErrors();
}
