#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<std::string>(
            propertyGrettingName, sdbusplus::vtable::property_::const_,
            [this](const auto&) { return greetings_; });

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

        demo_->register_property_r<uint32_t>(
            propertyValueName, 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();
}
