#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 <iostream>

namespace xyz
{
namespace demo
{

const std::string path = "/xyz/demo";
const std::string name = "xyz.demo";

} // namespace demo
} // namespace xyz

namespace name
{

const std::string greetings = "Greetings";
const std::string goodbyes = "Goodbyes";

} // namespace name

namespace utils
{

template <class T>
class Property
{
  public:
    Property(sdbusplus::asio::connection& bus, std::string_view service,
             std::string_view path, std::string_view interface,
             std::string_view name) :
        bus_(bus),
        service_(service), path_(path), interface_(interface), name_(name)
    {}

    template <class OnError, class OnSuccess>
    void async_get(OnError&& onError, OnSuccess&& onSuccess)
    {
        sdbusplus::asio::getProperty<T>(bus_, service_, path_, interface_,
                                        name_, std::forward<OnError>(onError),
                                        std::forward<OnSuccess>(onSuccess));
    }

    template <class OnError, class OnSuccess>
    void async_set(const T& value, OnError&& onError, OnSuccess&& onSuccess)
    {
        sdbusplus::asio::setProperty(bus_, service_, path_, interface_, name_,
                                     value, std::forward<OnError>(onError),
                                     std::forward<OnSuccess>(onSuccess));
    }

  private:
    sdbusplus::asio::connection& bus_;
    std::string service_;
    std::string path_;
    std::string interface_;
    std::string name_;
};

} // namespace utils

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(
            xyz::demo::path, xyz::demo::name,
            [this](sdbusplus::asio::dbus_interface& demo) {
                demo.register_property_r(
                    name::greetings, std::string(),
                    sdbusplus::vtable::property_::const_,
                    [this](const auto&) { return greetings_; });

                demo.register_property_rw(
                    name::goodbyes, std::string(),
                    sdbusplus::vtable::property_::emits_change,
                    [this](const auto& newPropertyValue, const auto&) {
                        goodbyes_ = newPropertyValue;
                        return 1;
                    },
                    [this](const auto&) { return goodbyes_; });
            });
    }

    uint32_t fatalErrors() const
    {
        return fatalErrors_;
    }

    auto getFailed()
    {
        return [this](boost::system::error_code error) {
            std::cerr << "Error: getProperty failed " << error << "\n";
            ++fatalErrors_;
        };
    }

    void asyncReadPropertyWithIncorrectType()
    {
        utils::Property<uint32_t> propertyWithWrongType{
            bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
            name::greetings};

        propertyWithWrongType.async_get(
            [](boost::system::error_code error) {
                std::cout
                    << "As expected failed to getProperty with wrong type: "
                    << error << "\n";
            },
            [this](uint32_t) {
                std::cerr << "Error: it was expected to fail getProperty due "
                             "to wrong type\n";
                ++fatalErrors_;
            });
    }

    void asyncReadProperties()
    {
        propertyGreetings.async_get(getFailed(), [](std::string value) {
            std::cout << "Greetings value is: " << value << "\n";
        });

        propertyGoodbyes.async_get(getFailed(), [](std::string value) {
            std::cout << "Goodbyes value is: " << value << "\n";
        });
    }

    void asyncChangeProperty()
    {
        propertyGreetings.async_set(
            "Hi, hey, hello",
            [](const boost::system::error_code& error) {
                std::cout << "As expected, failed to set greetings property: "
                          << error << "\n";
            },
            [this]() {
                std::cout
                    << "Error: it was expected to fail to change greetings\n";
                ++fatalErrors_;
            });

        propertyGoodbyes.async_set(
            "Bye bye",
            [this](const boost::system::error_code& error) {
                std::cout << "Error: it supposed to be ok to change goodbyes "
                             "property: "
                          << error << "\n";
                ++fatalErrors_;
            },
            [this]() {
                std::cout << "Changed goodbyes property as expected\n";
                boost::asio::post(ioc_, [this] { asyncReadProperties(); });
            });
    }

    void syncChangeGoodbyes(std::string_view value)
    {
        goodbyes_ = value;
        demo_->signal_property(name::goodbyes);
    }

  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;

    utils::Property<std::string> propertyGreetings{
        bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
        name::greetings};
    utils::Property<std::string> propertyGoodbyes{
        bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
        name::goodbyes};
};

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(xyz::demo::name.c_str());

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

    app.syncChangeGoodbyes("Good bye");

    boost::asio::post(ioc,
                      [&app] { app.asyncReadPropertyWithIncorrectType(); });
    boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
    boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });

    ioc.run();

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

    return app.fatalErrors();
}
