/**
 * 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 "config.h"

#include "manager.hpp"
#include "xyz/openbmc_project/Example/Iface1/server.hpp"
#include "xyz/openbmc_project/Example/Iface2/server.hpp"

#include <algorithm>
#include <cassert>
#include <chrono>
#include <iostream>
#include <thread>

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(sdbusplus::message::variant_ns::get<std::string>(
                       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
