#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 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:
    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();
}
