#include <boost/asio/io_context.hpp>
#include <boost/asio/signal_set.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(sdbusplus::asio::connection& bus,
                sdbusplus::asio::object_server& objServer) :
        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 true;
            },
            [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 logUnpackError(const sdbusplus::UnpackErrorReason reason,
                        const std::string& property)
    {
        std::cerr << "UnpackError: " << static_cast<int>(reason) << ", "
                  << property << "\n";
        ++fatalErrors_;
    }

    void logExpectedException(
        const sdbusplus::exception::UnpackPropertyError& error)
    {
        std::cout << "As expected " << error.what() << "\n";
    }

    void asyncGetAllPropertiesStringTypeOnly()
    {
        sdbusplus::asio::getAllProperties(
            bus_, demoServiceName, demoObjectPath, demoInterfaceName,
            [this](const boost::system::error_code ec,
                   const std::vector<std::pair<
                       std::string, std::variant<std::monostate, std::string>>>&
                       properties) -> void {
                if (ec)
                {
                    logSystemErrorCode(ec);
                    return;
                }
                {
                    const std::string* greetings = nullptr;
                    const std::string* goodbyes = nullptr;
                    const bool success = sdbusplus::unpackPropertiesNoThrow(
                        [this](const sdbusplus::UnpackErrorReason reason,
                               const std::string& property) {
                    logUnpackError(reason, property);
                        },
                        properties, propertyGrettingName, greetings,
                        propertyGoodbyesName, goodbyes);

                    if (success)
                    {
                        std::cout << "value of greetings: " << *greetings
                                  << "\n";
                        std::cout << "value of goodbyes: " << *goodbyes << "\n";
                    }
                    else
                    {
                        ++fatalErrors_;
                    }
                }

                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](const boost::system::error_code ec,
                   const 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:
    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(*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();
}
