/**
 * 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;

using Object = phosphor::inventory::manager::Object;
using ObjectMap = std::map<sdbusplus::message::object_path, Object>;

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 auto trigger5 =
    sdbusplus::message::object_path(EXAMPLE_ROOT + "/trigger5"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());
        sdbusplus::server::object::object<ExampleIface1, ExampleIface2> t5(
            bus, trigger5.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::bus::match_t _match;
    sdbusplus::message::message _next;
};

/**@brief Find a subset of interfaces and properties in an object. */
auto hasProperties(const Object& l, const Object& r)
{
    Object 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. */
auto hasInterfaces(const std::vector<std::string>& l, const Object& 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 obj{
        {"xyz.openbmc_project.Example.Iface1",
         {{"ExampleProperty1", "test1"s}}},
        {"xyz.openbmc_project.Example.Iface2",
         {{"ExampleProperty2", "test2"s},
          {"ExampleProperty3", static_cast<int64_t>(0ll)}}},
    };

    // Validate startup events occurred.
    {
        sdbusplus::message::object_path relCreateMe3{"/createme3"};
        std::string createMe3{root + relCreateMe3.str};

        auto get =
            b.new_method_call(MGR_SERVICE, createMe3.c_str(),
                              "org.freedesktop.DBus.Properties", "GetAll");
        get.append("xyz.openbmc_project.Example.Iface1");
        auto resp = b.call(get);

        Object::mapped_type properties;
        assert(!resp.is_method_error());
        resp.read(properties);
    }

    // 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(ObjectMap({{relPath, obj}}));
        b.call(m);

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

    // Validate the propertyIs filter.
    {// Create an object to be deleted.
     {auto m = notify();
    m.append(ObjectMap({{relDeleteMeThree, 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(static_cast<bool>(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(ObjectMap({{relDeleteMeOne, obj}}));
b.call(m);
}
{
    auto m = notify();
    m.append(ObjectMap({{relDeleteMeTwo, obj}}));
    b.call(m);
}
{
    auto m = notify();
    m.append(ObjectMap({{relDeleteMeThree, 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(static_cast<bool>(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(static_cast<bool>(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(static_cast<bool>(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(ObjectMap({{relChangeMe, 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");
        }
    }
}

// Validate the create object action.
{
    sdbusplus::message::object_path relCreateMe1{"/createme1"};
    sdbusplus::message::object_path relCreateMe2{"/createme2"};
    std::string createMe1{root + relCreateMe1.str};
    std::string createMe2{root + relCreateMe2.str};

    // Trigger the action.
    {
        sdbusplus::message::object_path signalPath;
        Object signalObject;

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

        auto m = set(trigger5.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(static_cast<bool>(sig));
            sig.read(signalPath);
            assert(createMe1 == signalPath.str);
            sig.read(signalObject);
        }
        {
            auto sig{queue.pop()};
            assert(static_cast<bool>(sig));
            sig.read(signalPath);
            assert(createMe2 == signalPath.str);
            sig.read(signalObject);
        }

        auto moreSignals{queue.pop()};
        assert(!moreSignals);
    }
}
}

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
