/**
 * 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 auto trigger4 = sdbusplus::message::object_path(EXAMPLE_ROOT +
                      "/trigger4"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());
        sdbusplus::server::object::object <
        ExampleIface1, ExampleIface2 > t4(bus, trigger4.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);
    }

    // Validate the propertyIs filter.
    {
        // Create an object to be deleted.
        {
            auto m = notify();
            m.append(relDeleteMeThree);
            m.append(obj);
            b.call(m);
        }

        // Validate that the action does not run if the property doesn't match.
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(trigger4.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("123"));
            b.call(m);
            auto sig{queue.pop()};
            assert(!sig);
        }

        // Validate that the action does run if the property matches.
        {
            // Set ExampleProperty2 to something else to the 123 filter
            // matches.
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(trigger4.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("xyz"));
            b.call(m);
            auto sig{queue.pop()};
            assert(!sig);
        }
        {
            // Set ExampleProperty3 to 99.
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(trigger4.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty3");
            m.append(sdbusplus::message::variant<int64_t>(99));
            b.call(m);
            auto sig{queue.pop()};
            assert(!sig);
        }
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(trigger4.str);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("123"));
            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 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
