/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "../manager.hpp"
#include "../config.h"
#include <cassert>
#include <iostream>
#include <algorithm>
#include <thread>
#include <chrono>
#include <xyz/openbmc_project/Example/Iface1/server.hpp>
#include <xyz/openbmc_project/Example/Iface2/server.hpp>

using namespace std::literals::chrono_literals;
using namespace std::literals::string_literals;

constexpr auto MGR_SERVICE = "phosphor.inventory.test.mgr";
constexpr auto MGR_INTERFACE = IFACE;
constexpr auto MGR_ROOT = "/testing/inventory";
constexpr auto EXAMPLE_SERVICE = "phosphor.inventory.test.example";
constexpr auto EXAMPLE_ROOT = "/testing";

const auto trigger1 = sdbusplus::message::object_path(EXAMPLE_ROOT +
                      "/trigger1"s);
const auto trigger2 = sdbusplus::message::object_path(EXAMPLE_ROOT +
                      "/trigger2"s);
const auto trigger3 = sdbusplus::message::object_path(EXAMPLE_ROOT +
                      "/trigger3"s);

const sdbusplus::message::object_path relDeleteMeOne{"/deleteme1"};
const sdbusplus::message::object_path relDeleteMeTwo{"/deleteme2"};
const sdbusplus::message::object_path relDeleteMeThree{"/deleteme3"};

const std::string root{MGR_ROOT};
const std::string deleteMeOne{root + relDeleteMeOne.str};
const std::string deleteMeTwo{root + relDeleteMeTwo.str};
const std::string deleteMeThree{root + relDeleteMeThree.str};

using ExampleIface1 = sdbusplus::xyz::openbmc_project::Example::server::Iface1;
using ExampleIface2 = sdbusplus::xyz::openbmc_project::Example::server::Iface2;

/** @class ExampleService
 *  @brief Host an object for triggering events.
 */
struct ExampleService
{
    ~ExampleService() = default;
    ExampleService() :
        shutdown(false),
        bus(sdbusplus::bus::new_default()),
        objmgr(sdbusplus::server::manager::manager(bus, MGR_ROOT))
    {
        bus.request_name(EXAMPLE_SERVICE);
    }

    void run()
    {
        sdbusplus::server::object::object <
        ExampleIface1, ExampleIface2 > t1(bus, trigger1.str.c_str());
        sdbusplus::server::object::object <
        ExampleIface1, ExampleIface2 > t2(bus, trigger2.str.c_str());
        sdbusplus::server::object::object <
        ExampleIface1, ExampleIface2 > t3(bus, trigger3.str.c_str());

        while (!shutdown)
        {
            bus.process_discard();
            bus.wait((5000000us).count());
        }
    }

    volatile bool shutdown;
    sdbusplus::bus::bus bus;
    sdbusplus::server::manager::manager objmgr;
};

/** @class SignalQueue
 *  @brief Store DBus signals in a queue.
 */
class SignalQueue
{
    public:
        ~SignalQueue() = default;
        SignalQueue() = delete;
        SignalQueue(const SignalQueue&) = delete;
        SignalQueue(SignalQueue&&) = default;
        SignalQueue& operator=(const SignalQueue&) = delete;
        SignalQueue& operator=(SignalQueue&&) = default;
        explicit SignalQueue(const std::string& match) :
            _bus(sdbusplus::bus::new_default()),
            _match(_bus, match.c_str(), &callback, this),
            _next(nullptr)
        {
        }

        auto&& pop(unsigned timeout = 1000000)
        {
            while (timeout > 0 && !_next)
            {
                _bus.process_discard();
                _bus.wait(50000);
                timeout -= 50000;
            }
            return std::move(_next);
        }

    private:
        static int callback(sd_bus_message* m, void* context, sd_bus_error*)
        {
            auto* me = static_cast<SignalQueue*>(context);
            sd_bus_message_ref(m);
            sdbusplus::message::message msg{m};
            me->_next = std::move(msg);
            return 0;
        }

        sdbusplus::bus::bus _bus;
        sdbusplus::server::match::match _match;
        sdbusplus::message::message _next;
};

template <typename ...T>
using Object = std::map <
               std::string,
               std::map <
               std::string,
               sdbusplus::message::variant<T... >>>;

/**@brief Find a subset of interfaces and properties in an object. */
template <typename ...T>
auto hasProperties(const Object<T...>& l, const Object<T...>& r)
{
    Object<T...> result;
    std::set_difference(
        r.cbegin(),
        r.cend(),
        l.cbegin(),
        l.cend(),
        std::inserter(result, result.end()));
    return result.empty();
}

/**@brief Check an object for one or more interfaces. */
template <typename ...T>
auto hasInterfaces(const std::vector<std::string>& l, const Object<T...>& r)
{
    std::vector<std::string> stripped, interfaces;
    std::transform(
        r.cbegin(),
        r.cend(),
        std::back_inserter(stripped),
        [](auto & p)
    {
        return p.first;
    });
    std::set_difference(
        stripped.cbegin(),
        stripped.cend(),
        l.cbegin(),
        l.cend(),
        std::back_inserter(interfaces));
    return interfaces.empty();
}

void runTests()
{
    const std::string exampleRoot{EXAMPLE_ROOT};
    auto b = sdbusplus::bus::new_default();

    auto notify = [&]()
    {
        return b.new_method_call(
                   MGR_SERVICE,
                   MGR_ROOT,
                   MGR_INTERFACE,
                   "Notify");
    };
    auto set = [&](const std::string & path)
    {
        return b.new_method_call(
                   EXAMPLE_SERVICE,
                   path.c_str(),
                   "org.freedesktop.DBus.Properties",
                   "Set");
    };

    Object<std::string> obj
    {
        {
            "xyz.openbmc_project.Example.Iface1",
            {{"ExampleProperty1", "test1"}}
        },
        {
            "xyz.openbmc_project.Example.Iface2",
            {{"ExampleProperty2", "test2"}}
        },
    };

    // Make sure the notify method works.
    {
        sdbusplus::message::object_path relPath{"/foo"};
        std::string path(root + relPath.str);

        SignalQueue queue(
            "path='" + root + "',member='InterfacesAdded'");

        auto m = notify();
        m.append(relPath);
        m.append(obj);
        b.call(m);

        auto sig{queue.pop()};
        assert(sig);
        sdbusplus::message::object_path signalPath;
        Object<std::string> signalObject;
        sig.read(signalPath);
        assert(path == signalPath.str);
        sig.read(signalObject);
        assert(hasProperties(signalObject, obj));
        auto moreSignals{queue.pop()};
        assert(!moreSignals);
    }

    // Make sure DBus signals are handled.
    {
        // Create some objects to be deleted by an action.
        {
            auto m = notify();
            m.append(relDeleteMeOne);
            m.append(obj);
            b.call(m);
        }
        {
            auto m = notify();
            m.append(relDeleteMeTwo);
            m.append(obj);
            b.call(m);
        }
        {
            auto m = notify();
            m.append(relDeleteMeThree);
            m.append(obj);
            b.call(m);
        }

        // Set some properties that should not trigger due to a filter.
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(trigger1.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("abc123"));
            b.call(m);
            auto sig{queue.pop()};
            assert(!sig);
        }
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(trigger3.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty3");
            m.append(sdbusplus::message::variant<int64_t>(11));
            b.call(m);
            auto sig{queue.pop()};
            assert(!sig);
        }

        // Set some properties that should trigger.
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");

            auto m = set(trigger1.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("xxxyyy"));
            b.call(m);

            sdbusplus::message::object_path sigpath;
            std::vector<std::string> interfaces;
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                assert(sig);
                sig.read(sigpath);
                assert(sigpath == deleteMeOne);
                sig.read(interfaces);
                std::sort(interfaces.begin(), interfaces.end());
                assert(hasInterfaces(interfaces, obj));
            }
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                assert(sig);
                sig.read(sigpath);
                assert(sigpath == deleteMeTwo);
                sig.read(interfaces);
                std::sort(interfaces.begin(), interfaces.end());
                assert(hasInterfaces(interfaces, obj));
            }
            {
                // Make sure there were only two signals.
                auto sig{queue.pop()};
                assert(!sig);
            }
        }
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");

            auto m = set(trigger3.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty3");
            m.append(sdbusplus::message::variant<int64_t>(10));
            b.call(m);

            sdbusplus::message::object_path sigpath;
            std::vector<std::string> interfaces;
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                assert(sig);
                sig.read(sigpath);
                assert(sigpath == deleteMeThree);
                sig.read(interfaces);
                std::sort(interfaces.begin(), interfaces.end());
                assert(hasInterfaces(interfaces, obj));
            }
            {
                // Make sure there was only one signal.
                auto sig{queue.pop()};
                assert(!sig);
            }
        }
    }

    // Validate the set property action.
    {
        sdbusplus::message::object_path relChangeMe{"/changeme"};
        std::string changeMe{root + relChangeMe.str};

        // Create an object to be updated by the set property action.
        {
            auto m = notify();
            m.append(relChangeMe);
            m.append(obj);
            b.call(m);
        }

        // Trigger and validate the change.
        {
            SignalQueue queue(
                "path='" + changeMe + "',member='PropertiesChanged'");
            auto m = set(trigger2.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("yyyxxx"));
            b.call(m);

            std::string sigInterface;
            std::map <
            std::string,
                sdbusplus::message::variant<std::string >> sigProperties;
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                sig.read(sigInterface);
                assert(sigInterface == "xyz.openbmc_project.Example.Iface1");
                sig.read(sigProperties);
                assert(sigProperties["ExampleProperty1"] == "changed");
            }
        }
    }
}

int main()
{
    phosphor::inventory::manager::Manager mgr(
        sdbusplus::bus::new_default(),
        MGR_SERVICE, MGR_ROOT, MGR_INTERFACE);
    ExampleService d;

    auto f1 = [](auto mgr)
    {
        mgr->run();
    };
    auto f2 = [](auto d)
    {
        d->run();
    };

    auto t1 = std::thread(f1, &mgr);
    auto t2 = std::thread(f2, &d);

    runTests();

    mgr.shutdown();
    d.shutdown = true;

    // Wait for server threads to exit.
    t1.join();
    t2.join();
    std::cout << "Success!  Waiting for threads to exit..." << std::endl;

    return 0;
}

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
